am 11820f73: Merge "Allow acquiring ContentProviders across users." into jb-mr1-dev

* commit '11820f7386ce86fd89e9e6b49d9231dce6e1ed07':
  Allow acquiring ContentProviders across users.
This commit is contained in:
Jeff Sharkey
2012-09-24 09:28:22 -07:00
committed by Android Git Automerger
15 changed files with 235 additions and 109 deletions

View File

@ -25,6 +25,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.UserHandle;
import android.text.TextUtils;
/**
@ -63,7 +64,8 @@ public class Content {
private static final String USAGE =
"usage: adb shell content [subcommand] [options]\n"
+ "\n"
+ "usage: adb shell content insert --uri <URI> --bind <BINDING> [--bind <BINDING>...]\n"
+ "usage: adb shell content insert --uri <URI> [--user <USER_ID>]"
+ " --bind <BINDING> [--bind <BINDING>...]\n"
+ " <URI> a content provider URI.\n"
+ " <BINDING> binds a typed value to a column and is formatted:\n"
+ " <COLUMN_NAME>:<TYPE>:<COLUMN_VALUE> where:\n"
@ -75,7 +77,7 @@ public class Content {
+ " adb shell content insert --uri content://settings/secure --bind name:s:new_setting"
+ " --bind value:s:new_value\n"
+ "\n"
+ "usage: adb shell content update --uri <URI> [--where <WHERE>]\n"
+ "usage: adb shell content update --uri <URI> [--user <USER_ID>] [--where <WHERE>]\n"
+ " <WHERE> is a SQL style where clause in quotes (You have to escape single quotes"
+ " - see example below).\n"
+ " Example:\n"
@ -83,15 +85,15 @@ public class Content {
+ " adb shell content update --uri content://settings/secure --bind"
+ " value:s:newer_value --where \"name=\'new_setting\'\"\n"
+ "\n"
+ "usage: adb shell content delete --uri <URI> --bind <BINDING>"
+ "usage: adb shell content delete --uri <URI> [--user <USER_ID>] --bind <BINDING>"
+ " [--bind <BINDING>...] [--where <WHERE>]\n"
+ " Example:\n"
+ " # Remove \"new_setting\" secure setting.\n"
+ " adb shell content delete --uri content://settings/secure "
+ "--where \"name=\'new_setting\'\"\n"
+ "\n"
+ "usage: adb shell content query --uri <URI> [--projection <PROJECTION>]"
+ " [--where <WHERE>] [--sort <SORT_ORDER>]\n"
+ "usage: adb shell content query --uri <URI> [--user <USER_ID>]"
+ " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]\n"
+ " <PROJECTION> is a list of colon separated column names and is formatted:\n"
+ " <COLUMN_NAME>[:<COLUMN_NAME>...]\n"
+ " <SORT_OREDER> is the order in which rows in the result should be sorted.\n"
@ -110,6 +112,7 @@ public class Content {
private static final String ARGUMENT_WHERE = "--where";
private static final String ARGUMENT_BIND = "--bind";
private static final String ARGUMENT_URI = "--uri";
private static final String ARGUMENT_USER = "--user";
private static final String ARGUMENT_PROJECTION = "--projection";
private static final String ARGUMENT_SORT = "--sort";
private static final String TYPE_BOOLEAN = "b";
@ -150,10 +153,13 @@ public class Content {
private InsertCommand parseInsertCommand() {
Uri uri = null;
int userId = UserHandle.USER_OWNER;
ContentValues values = new ContentValues();
for (String argument; (argument = mTokenizer.nextArg()) != null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
} else if (ARGUMENT_USER.equals(argument)) {
userId = Integer.parseInt(argumentValueRequired(argument));
} else if (ARGUMENT_BIND.equals(argument)) {
parseBindValue(values);
} else {
@ -168,15 +174,18 @@ public class Content {
throw new IllegalArgumentException("Bindings not specified."
+ " Did you specify --bind argument(s)?");
}
return new InsertCommand(uri, values);
return new InsertCommand(uri, userId, values);
}
private DeleteCommand parseDeleteCommand() {
Uri uri = null;
int userId = UserHandle.USER_OWNER;
String where = null;
for (String argument; (argument = mTokenizer.nextArg())!= null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
} else if (ARGUMENT_USER.equals(argument)) {
userId = Integer.parseInt(argumentValueRequired(argument));
} else if (ARGUMENT_WHERE.equals(argument)) {
where = argumentValueRequired(argument);
} else {
@ -187,16 +196,19 @@ public class Content {
throw new IllegalArgumentException("Content provider URI not specified."
+ " Did you specify --uri argument?");
}
return new DeleteCommand(uri, where);
return new DeleteCommand(uri, userId, where);
}
private UpdateCommand parseUpdateCommand() {
Uri uri = null;
int userId = UserHandle.USER_OWNER;
String where = null;
ContentValues values = new ContentValues();
for (String argument; (argument = mTokenizer.nextArg())!= null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
} else if (ARGUMENT_USER.equals(argument)) {
userId = Integer.parseInt(argumentValueRequired(argument));
} else if (ARGUMENT_WHERE.equals(argument)) {
where = argumentValueRequired(argument);
} else if (ARGUMENT_BIND.equals(argument)) {
@ -213,17 +225,20 @@ public class Content {
throw new IllegalArgumentException("Bindings not specified."
+ " Did you specify --bind argument(s)?");
}
return new UpdateCommand(uri, values, where);
return new UpdateCommand(uri, userId, values, where);
}
public QueryCommand parseQueryCommand() {
Uri uri = null;
int userId = UserHandle.USER_OWNER;
String[] projection = null;
String sort = null;
String where = null;
for (String argument; (argument = mTokenizer.nextArg())!= null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
} else if (ARGUMENT_USER.equals(argument)) {
userId = Integer.parseInt(argumentValueRequired(argument));
} else if (ARGUMENT_WHERE.equals(argument)) {
where = argumentValueRequired(argument);
} else if (ARGUMENT_SORT.equals(argument)) {
@ -238,7 +253,7 @@ public class Content {
throw new IllegalArgumentException("Content provider URI not specified."
+ " Did you specify --uri argument?");
}
return new QueryCommand(uri, projection, where, sort);
return new QueryCommand(uri, userId, projection, where, sort);
}
private void parseBindValue(ContentValues values) {
@ -298,9 +313,11 @@ public class Content {
private static abstract class Command {
final Uri mUri;
final int mUserId;
public Command(Uri uri) {
public Command(Uri uri, int userId) {
mUri = uri;
mUserId = userId;
}
public final void execute() {
@ -311,7 +328,7 @@ public class Content {
IBinder token = new Binder();
try {
ContentProviderHolder holder = activityManager.getContentProviderExternal(
providerName, token);
providerName, mUserId, token);
if (holder == null) {
throw new IllegalStateException("Could not find provider: " + providerName);
}
@ -334,8 +351,8 @@ public class Content {
private static class InsertCommand extends Command {
final ContentValues mContentValues;
public InsertCommand(Uri uri, ContentValues contentValues) {
super(uri);
public InsertCommand(Uri uri, int userId, ContentValues contentValues) {
super(uri, userId);
mContentValues = contentValues;
}
@ -348,8 +365,8 @@ public class Content {
private static class DeleteCommand extends Command {
final String mWhere;
public DeleteCommand(Uri uri, String where) {
super(uri);
public DeleteCommand(Uri uri, int userId, String where) {
super(uri, userId);
mWhere = where;
}
@ -363,8 +380,9 @@ public class Content {
final String[] mProjection;
final String mSortOrder;
public QueryCommand(Uri uri, String[] projection, String where, String sortOrder) {
super(uri, where);
public QueryCommand(
Uri uri, int userId, String[] projection, String where, String sortOrder) {
super(uri, userId, where);
mProjection = projection;
mSortOrder = sortOrder;
}
@ -426,8 +444,8 @@ public class Content {
private static class UpdateCommand extends InsertCommand {
final String mWhere;
public UpdateCommand(Uri uri, ContentValues contentValues, String where) {
super(uri, contentValues);
public UpdateCommand(Uri uri, int userId, ContentValues contentValues, String where) {
super(uri, userId, contentValues);
mWhere = where;
}

View File

@ -632,8 +632,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String name = data.readString();
int userId = data.readInt();
boolean stable = data.readInt() != 0;
ContentProviderHolder cph = getContentProvider(app, name, stable);
ContentProviderHolder cph = getContentProvider(app, name, userId, stable);
reply.writeNoException();
if (cph != null) {
reply.writeInt(1);
@ -647,8 +648,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String name = data.readString();
int userId = data.readInt();
IBinder token = data.readStrongBinder();
ContentProviderHolder cph = getContentProviderExternal(name, token);
ContentProviderHolder cph = getContentProviderExternal(name, userId, token);
reply.writeNoException();
if (cph != null) {
reply.writeInt(1);
@ -2495,12 +2497,13 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
public ContentProviderHolder getContentProvider(IApplicationThread caller,
String name, boolean stable) throws RemoteException {
String name, int userId, boolean stable) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(name);
data.writeInt(userId);
data.writeInt(stable ? 1 : 0);
mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
reply.readException();
@ -2513,13 +2516,13 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return cph;
}
public ContentProviderHolder getContentProviderExternal(String name, IBinder token)
throws RemoteException
{
public ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeString(name);
data.writeInt(userId);
data.writeStrongBinder(token);
mRemote.transact(GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION, data, reply, 0);
reply.readException();

View File

@ -89,6 +89,7 @@ import android.renderscript.RenderScript;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.internal.util.Objects;
import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
@ -214,9 +215,33 @@ public final class ActivityThread {
= new ArrayList<ActivityClientRecord>();
Configuration mPendingConfiguration = null;
private static final class ProviderKey {
final String authority;
final int userId;
public ProviderKey(String authority, int userId) {
this.authority = authority;
this.userId = userId;
}
@Override
public boolean equals(Object o) {
if (o instanceof ProviderKey) {
final ProviderKey other = (ProviderKey) o;
return Objects.equal(authority, other.authority) && userId == other.userId;
}
return false;
}
@Override
public int hashCode() {
return ((authority != null) ? authority.hashCode() : 0) ^ userId;
}
}
// The lock of mProviderMap protects the following variables.
final HashMap<String, ProviderClientRecord> mProviderMap
= new HashMap<String, ProviderClientRecord>();
final HashMap<ProviderKey, ProviderClientRecord> mProviderMap
= new HashMap<ProviderKey, ProviderClientRecord>();
final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
= new HashMap<IBinder, ProviderRefCount>();
final HashMap<IBinder, ProviderClientRecord> mLocalProviders
@ -4360,8 +4385,9 @@ public final class ActivityThread {
}
}
public final IContentProvider acquireProvider(Context c, String name, boolean stable) {
IContentProvider provider = acquireExistingProvider(c, name, stable);
public final IContentProvider acquireProvider(
Context c, String auth, int userId, boolean stable) {
final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
if (provider != null) {
return provider;
}
@ -4375,11 +4401,11 @@ public final class ActivityThread {
IActivityManager.ContentProviderHolder holder = null;
try {
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), name, stable);
getApplicationThread(), auth, userId, stable);
} catch (RemoteException ex) {
}
if (holder == null) {
Slog.e(TAG, "Failed to find provider info for " + name);
Slog.e(TAG, "Failed to find provider info for " + auth);
return null;
}
@ -4456,10 +4482,11 @@ public final class ActivityThread {
}
}
public final IContentProvider acquireExistingProvider(Context c, String name,
boolean stable) {
public final IContentProvider acquireExistingProvider(
Context c, String auth, int userId, boolean stable) {
synchronized (mProviderMap) {
ProviderClientRecord pr = mProviderMap.get(name);
final ProviderKey key = new ProviderKey(auth, userId);
final ProviderClientRecord pr = mProviderMap.get(key);
if (pr == null) {
return null;
}
@ -4639,17 +4666,20 @@ public final class ActivityThread {
}
private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
ContentProvider localProvider,IActivityManager.ContentProviderHolder holder) {
String names[] = PATTERN_SEMICOLON.split(holder.info.authority);
ProviderClientRecord pcr = new ProviderClientRecord(names, provider,
localProvider, holder);
for (int i = 0; i < names.length; i++) {
ProviderClientRecord existing = mProviderMap.get(names[i]);
ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {
final String auths[] = PATTERN_SEMICOLON.split(holder.info.authority);
final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
final ProviderClientRecord pcr = new ProviderClientRecord(
auths, provider, localProvider, holder);
for (String auth : auths) {
final ProviderKey key = new ProviderKey(auth, userId);
final ProviderClientRecord existing = mProviderMap.get(key);
if (existing != null) {
Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
+ " already published as " + names[i]);
+ " already published as " + auth);
} else {
mProviderMap.put(names[i], pcr);
mProviderMap.put(key, pcr);
}
}
return pcr;

View File

@ -17,6 +17,7 @@
package android.app;
import com.android.internal.policy.PolicyManager;
import com.android.internal.util.Preconditions;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
@ -35,6 +36,7 @@ import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@ -183,6 +185,7 @@ class ContextImpl extends Context {
private Display mDisplay; // may be null if default display
private Context mReceiverRestrictedContext = null;
private boolean mRestricted;
private UserHandle mUser;
private final Object mSync = new Object();
@ -1676,7 +1679,13 @@ class ContextImpl extends Context {
@Override
public Context createPackageContext(String packageName, int flags)
throws PackageManager.NameNotFoundException {
throws NameNotFoundException {
return createPackageContextAsUser(packageName, flags, Process.myUserHandle());
}
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws NameNotFoundException {
if (packageName.equals("system") || packageName.equals("android")) {
final ContextImpl context = new ContextImpl(mMainThread.getSystemContext());
context.mBasePackageName = mBasePackageName;
@ -1688,7 +1697,7 @@ class ContextImpl extends Context {
if (pi != null) {
ContextImpl c = new ContextImpl();
c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
c.init(pi, null, mMainThread, mResources, mBasePackageName);
c.init(pi, null, mMainThread, mResources, mBasePackageName, user);
if (c.mResources != null) {
return c;
}
@ -1769,8 +1778,8 @@ class ContextImpl extends Context {
}
static ContextImpl createSystemContext(ActivityThread mainThread) {
ContextImpl context = new ContextImpl();
context.init(Resources.getSystem(), mainThread);
final ContextImpl context = new ContextImpl();
context.init(Resources.getSystem(), mainThread, Process.myUserHandle());
return context;
}
@ -1790,18 +1799,17 @@ class ContextImpl extends Context {
mResources = context.mResources;
mMainThread = context.mMainThread;
mContentResolver = context.mContentResolver;
mUser = context.mUser;
mDisplay = context.mDisplay;
mOuterContext = this;
}
final void init(LoadedApk packageInfo,
IBinder activityToken, ActivityThread mainThread) {
init(packageInfo, activityToken, mainThread, null, null);
final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) {
init(packageInfo, activityToken, mainThread, null, null, Process.myUserHandle());
}
final void init(LoadedApk packageInfo,
IBinder activityToken, ActivityThread mainThread,
Resources container, String basePackageName) {
final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread,
Resources container, String basePackageName, UserHandle user) {
mPackageInfo = packageInfo;
mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
mResources = mPackageInfo.getResources(mainThread);
@ -1818,16 +1826,18 @@ class ContextImpl extends Context {
null, container.getCompatibilityInfo());
}
mMainThread = mainThread;
mContentResolver = new ApplicationContentResolver(this, mainThread);
mActivityToken = activityToken;
mContentResolver = new ApplicationContentResolver(this, mainThread, user);
mUser = user;
}
final void init(Resources resources, ActivityThread mainThread) {
final void init(Resources resources, ActivityThread mainThread, UserHandle user) {
mPackageInfo = null;
mBasePackageName = null;
mResources = resources;
mMainThread = mainThread;
mContentResolver = new ApplicationContentResolver(this, mainThread);
mContentResolver = new ApplicationContentResolver(this, mainThread, user);
mUser = user;
}
final void scheduleFinalCleanup(String who, String what) {
@ -1912,19 +1922,24 @@ class ContextImpl extends Context {
// ----------------------------------------------------------------------
private static final class ApplicationContentResolver extends ContentResolver {
public ApplicationContentResolver(Context context, ActivityThread mainThread) {
private final ActivityThread mMainThread;
private final UserHandle mUser;
public ApplicationContentResolver(
Context context, ActivityThread mainThread, UserHandle user) {
super(context);
mMainThread = mainThread;
mMainThread = Preconditions.checkNotNull(mainThread);
mUser = Preconditions.checkNotNull(user);
}
@Override
protected IContentProvider acquireProvider(Context context, String name) {
return mMainThread.acquireProvider(context, name, true);
protected IContentProvider acquireProvider(Context context, String auth) {
return mMainThread.acquireProvider(context, auth, mUser.getIdentifier(), true);
}
@Override
protected IContentProvider acquireExistingProvider(Context context, String name) {
return mMainThread.acquireExistingProvider(context, name, true);
protected IContentProvider acquireExistingProvider(Context context, String auth) {
return mMainThread.acquireExistingProvider(context, auth, mUser.getIdentifier(), true);
}
@Override
@ -1933,8 +1948,8 @@ class ContextImpl extends Context {
}
@Override
protected IContentProvider acquireUnstableProvider(Context c, String name) {
return mMainThread.acquireProvider(c, name, false);
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
return mMainThread.acquireProvider(c, auth, mUser.getIdentifier(), false);
}
@Override
@ -1946,7 +1961,5 @@ class ContextImpl extends Context {
public void unstableProviderDied(IContentProvider icp) {
mMainThread.handleUnstableProviderDied(icp.asBinder(), true);
}
private final ActivityThread mMainThread;
}
}

View File

@ -117,8 +117,8 @@ public interface IActivityManager extends IInterface {
public void reportThumbnail(IBinder token,
Bitmap thumbnail, CharSequence description) throws RemoteException;
public ContentProviderHolder getContentProvider(IApplicationThread caller,
String name, boolean stable) throws RemoteException;
public ContentProviderHolder getContentProviderExternal(String name, IBinder token)
String name, int userId, boolean stable) throws RemoteException;
public ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token)
throws RemoteException;
public void removeContentProvider(IBinder connection, boolean stable) throws RemoteException;
public void removeContentProviderExternal(String name, IBinder token) throws RemoteException;

View File

@ -29,6 +29,7 @@ import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.IntProperty;
import android.util.Log;
@ -893,6 +894,19 @@ public class Notification implements Parcelable
return sb.toString();
}
/** {@hide} */
public void setUser(UserHandle user) {
if (tickerView != null) {
tickerView.setUser(user);
}
if (contentView != null) {
contentView.setUser(user);
}
if (bigContentView != null) {
bigContentView.setUser(user);
}
}
/**
* Builder class for {@link Notification} objects.
*

View File

@ -2573,6 +2573,17 @@ public abstract class Context {
public abstract Context createPackageContext(String packageName,
int flags) throws PackageManager.NameNotFoundException;
/**
* Similar to {@link #createPackageContext(String, int)}, but with a
* different {@link UserHandle}. For example, {@link #getContentResolver()}
* will open any {@link Uri} as the given user.
*
* @hide
*/
public abstract Context createPackageContextAsUser(
String packageName, int flags, UserHandle user)
throws PackageManager.NameNotFoundException;
/**
* Return a new Context object for the current Context but whose resources
* are adjusted to match the given Configuration. Each call to this method

View File

@ -586,6 +586,13 @@ public class ContextWrapper extends Context {
return mBase.createPackageContext(packageName, flags);
}
/** @hide */
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws PackageManager.NameNotFoundException {
return mBase.createPackageContextAsUser(packageName, flags, user);
}
@Override
public Context createConfigurationContext(Configuration overrideConfiguration) {
return mBase.createConfigurationContext(overrideConfiguration);

View File

@ -23,7 +23,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.graphics.Bitmap;
@ -35,9 +34,9 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.LayoutInflater.Filter;
import android.view.RemotableViewMethod;
@ -71,6 +70,13 @@ public class RemoteViews implements Parcelable, Filter {
*/
static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId";
/**
* User that these views should be applied as. Requires
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} when
* crossing user boundaries.
*/
private UserHandle mUser = android.os.Process.myUserHandle();
/**
* The package name of the package containing the layout
* resource. (Added to the parcel)
@ -1446,11 +1452,16 @@ public class RemoteViews implements Parcelable, Filter {
recalculateMemoryUsage();
}
/** {@hide} */
public void setUser(UserHandle user) {
mUser = user;
}
private boolean hasLandscapeAndPortraitLayouts() {
return (mLandscape != null) && (mPortrait != null);
}
/**
/**
* Create a new RemoteViews object that will inflate as the specified
* landspace or portrait RemoteViews, depending on the current configuration.
*
@ -2309,7 +2320,8 @@ public class RemoteViews implements Parcelable, Filter {
if (packageName != null) {
try {
c = context.createPackageContext(packageName, Context.CONTEXT_RESTRICTED);
c = context.createPackageContextAsUser(
packageName, Context.CONTEXT_RESTRICTED, mUser);
} catch (NameNotFoundException e) {
Log.e(LOG_TAG, "Package name " + packageName + " not found");
c = context;

View File

@ -20,8 +20,6 @@ import android.app.Notification;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.widget.RemoteViews;
/*
boolean clearable = !n.ongoingEvent && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
@ -39,19 +37,25 @@ if (truncatedTicker != null && truncatedTicker.length() > maxTickerLen) {
* Class encapsulating a Notification. Sent by the NotificationManagerService to the IStatusBar (in System UI).
*/
public class StatusBarNotification implements Parcelable {
public String pkg;
public int id;
public String tag;
public int uid;
public int initialPid;
public Notification notification;
public int score;
public StatusBarNotification() {
public final String pkg;
public final int id;
public final String tag;
public final int uid;
public final int initialPid;
// TODO: make this field private and move callers to an accessor that
// ensures sourceUser is applied.
public final Notification notification;
public final int score;
public final UserHandle user;
@Deprecated
public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
Notification notification) {
this(pkg, id, tag, uid, initialPid, score, notification, UserHandle.OWNER);
}
public StatusBarNotification(String pkg, int id, String tag,
int uid, int initialPid, int score, Notification notification) {
public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
Notification notification, UserHandle user) {
if (pkg == null) throw new NullPointerException();
if (notification == null) throw new NullPointerException();
@ -62,13 +66,11 @@ public class StatusBarNotification implements Parcelable {
this.initialPid = initialPid;
this.score = score;
this.notification = notification;
this.user = user;
this.notification.setUser(user);
}
public StatusBarNotification(Parcel in) {
readFromParcel(in);
}
public void readFromParcel(Parcel in) {
this.pkg = in.readString();
this.id = in.readInt();
if (in.readInt() != 0) {
@ -80,6 +82,8 @@ public class StatusBarNotification implements Parcelable {
this.initialPid = in.readInt();
this.score = in.readInt();
this.notification = new Notification(in);
this.user = UserHandle.readFromParcel(in);
this.notification.setUser(user);
}
public void writeToParcel(Parcel out, int flags) {
@ -95,6 +99,7 @@ public class StatusBarNotification implements Parcelable {
out.writeInt(this.initialPid);
out.writeInt(this.score);
this.notification.writeToParcel(out, flags);
user.writeToParcel(out, flags);
}
public int describeContents() {
@ -115,14 +120,16 @@ public class StatusBarNotification implements Parcelable {
}
};
@Override
public StatusBarNotification clone() {
return new StatusBarNotification(this.pkg, this.id, this.tag,
this.uid, this.initialPid, this.score, this.notification.clone());
return new StatusBarNotification(this.pkg, this.id, this.tag, this.uid, this.initialPid,
this.score, this.notification.clone(), this.user);
}
@Override
public String toString() {
return "StatusBarNotification(pkg=" + pkg + " id=" + id + " tag=" + tag
+ " score=" + score + " notn=" + notification + ")";
return "StatusBarNotification(pkg=" + pkg + " id=" + id + " tag=" + tag + " score=" + score
+ " notn=" + notification + " user=" + user + ")";
}
public boolean isOngoing() {
@ -139,5 +146,3 @@ public class StatusBarNotification implements Parcelable {
return UserHandle.getUserId(this.uid);
}
}

View File

@ -1370,9 +1370,8 @@ public class TabletStatusBar extends BaseStatusBar implements
iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
mNotificationDNDDummyEntry = new NotificationData.Entry(
null,
new StatusBarNotification("", 0, "", 0, 0, Notification.PRIORITY_MAX, dndNotification),
iconView);
null, new StatusBarNotification("", 0, "", 0, 0, Notification.PRIORITY_MAX,
dndNotification, android.os.Process.myUserHandle()), iconView);
mIconLayout.addView(iconView, params);
}

View File

@ -63,6 +63,7 @@ import android.util.Slog;
import android.util.Xml;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.android.internal.statusbar.StatusBarNotification;
@ -877,7 +878,6 @@ public class NotificationManagerService extends INotificationManager.Stub
return (x < low) ? low : ((x > high) ? high : x);
}
// Not exposed via Binder; for system use only (otherwise malicious apps could spoof the
// uid/pid of another application)
public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,
@ -992,8 +992,9 @@ public class NotificationManagerService extends INotificationManager.Stub
}
if (notification.icon != 0) {
StatusBarNotification n = new StatusBarNotification(pkg, id, tag,
r.uid, r.initialPid, score, notification);
final UserHandle user = new UserHandle(userId);
final StatusBarNotification n = new StatusBarNotification(
pkg, id, tag, r.uid, r.initialPid, score, notification, user);
if (old != null && old.statusBarKey != null) {
r.statusBarKey = old.statusBarKey;
long identity = Binder.clearCallingIdentity();

View File

@ -6414,10 +6414,6 @@ public final class ActivityManagerService extends ActivityManagerNative
+ " (pid=" + Binder.getCallingPid()
+ ") when getting content provider " + name);
}
if (r.userId != userId) {
throw new SecurityException("Calling requested user " + userId
+ " but app is user " + r.userId);
}
}
// First check if this content provider has been published...
@ -6666,7 +6662,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
public final ContentProviderHolder getContentProvider(
IApplicationThread caller, String name, boolean stable) {
IApplicationThread caller, String name, int userId, boolean stable) {
enforceNotIsolatedCaller("getContentProvider");
if (caller == null) {
String msg = "null IApplicationThread when getting content provider "
@ -6675,14 +6671,18 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
return getContentProviderImpl(caller, name, null, stable,
UserHandle.getCallingUserId());
userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, true, "getContentProvider", null);
return getContentProviderImpl(caller, name, null, stable, userId);
}
public ContentProviderHolder getContentProviderExternal(String name, IBinder token) {
public ContentProviderHolder getContentProviderExternal(
String name, int userId, IBinder token) {
enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
"Do not have permission in call getContentProviderExternal()");
return getContentProviderExternalUnchecked(name, token, UserHandle.getCallingUserId());
userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, true, "getContentProvider", null);
return getContentProviderExternalUnchecked(name, token, userId);
}
private ContentProviderHolder getContentProviderExternalUnchecked(String name,

View File

@ -523,6 +523,13 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
/** {@hide} */
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws PackageManager.NameNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public Context createConfigurationContext(Configuration overrideConfiguration) {
throw new UnsupportedOperationException();

View File

@ -919,6 +919,12 @@ public final class BridgeContext extends Context {
return null;
}
@Override
public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) {
// pass
return null;
}
@Override
public Context createConfigurationContext(Configuration overrideConfiguration) {
// pass