Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c7527ba authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android Git Automerger
Browse files

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

* commit '8bc3cfa3':
  Allow acquiring ContentProviders across users.
parents eeb8f979 8bc3cfa3
Loading
Loading
Loading
Loading
+37 −19
Original line number Diff line number Diff line
@@ -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;
        }

+9 −6
Original line number Diff line number Diff line
@@ -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();
+47 −17
Original line number Diff line number Diff line
@@ -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;
            }
@@ -4640,16 +4667,19 @@ 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]);
        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;
+36 −23
Original line number Diff line number Diff line
@@ -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;
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -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;
Loading