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

Commit e3f05441 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

resolved conflicts for merge of 2af632f8 to master

parents 3ff23c46 2af632f8
Loading
Loading
Loading
Loading
+113 −0
Original line number Diff line number Diff line
@@ -496,6 +496,17 @@
 visibility="public"
>
</field>
<field name="GLOBAL_SEARCH"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;android.permission.GLOBAL_SEARCH&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="HARDWARE_TEST"
 type="java.lang.String"
 transient="false"
@@ -28253,6 +28264,17 @@
 visibility="public"
>
</method>
<method name="getPathPermissions"
 return="android.content.pm.PathPermission[]"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getReadPermission"
 return="java.lang.String"
 abstract="false"
@@ -28455,6 +28477,19 @@
<parameter name="sortOrder" type="java.lang.String">
</parameter>
</method>
<method name="setPathPermissions"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="true"
 deprecated="not deprecated"
 visibility="protected"
>
<parameter name="permissions" type="android.content.pm.PathPermission[]">
</parameter>
</method>
<method name="setReadPermission"
 return="void"
 abstract="false"
@@ -41340,6 +41375,73 @@
>
</field>
</class>
<class name="PathPermission"
 extends="android.os.PatternMatcher"
 abstract="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<constructor name="PathPermission"
 type="android.content.pm.PathPermission"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="pattern" type="java.lang.String">
</parameter>
<parameter name="type" type="int">
</parameter>
<parameter name="readPermission" type="java.lang.String">
</parameter>
<parameter name="writePermission" type="java.lang.String">
</parameter>
</constructor>
<constructor name="PathPermission"
 type="android.content.pm.PathPermission"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="src" type="android.os.Parcel">
</parameter>
</constructor>
<method name="getReadPermission"
 return="java.lang.String"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getWritePermission"
 return="java.lang.String"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<field name="CREATOR"
 type="android.os.Parcelable.Creator"
 transient="false"
 volatile="false"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
</field>
</class>
<class name="PermissionGroupInfo"
 extends="android.content.pm.PackageItemInfo"
 abstract="false"
@@ -41669,6 +41771,17 @@
 visibility="public"
>
</field>
<field name="pathPermissions"
 type="android.content.pm.PathPermission[]"
 transient="false"
 volatile="false"
 value="null"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</field>
<field name="readPermission"
 type="java.lang.String"
 transient="false"
+117 −27
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.content;

import android.content.pm.PackageManager;
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
@@ -29,6 +30,7 @@ import android.database.SQLException;
import android.net.Uri;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.Process;

import java.io.File;
import java.io.FileNotFoundException;
@@ -66,8 +68,10 @@ import java.util.ArrayList;
 */
public abstract class ContentProvider implements ComponentCallbacks {
    private Context mContext = null;
    private int mMyUid;
    private String mReadPermission;
    private String mWritePermission;
    private PathPermission[] mPathPermissions;

    private Transport mTransport = new Transport();

@@ -109,31 +113,27 @@ public abstract class ContentProvider implements ComponentCallbacks {
        public IBulkCursor bulkQuery(Uri uri, String[] projection,
                String selection, String[] selectionArgs, String sortOrder,
                IContentObserver observer, CursorWindow window) {
            checkReadPermission(uri);
            enforceReadPermission(uri);
            Cursor cursor = ContentProvider.this.query(uri, projection,
                    selection, selectionArgs, sortOrder);
            if (cursor == null) {
                return null;
            }
            String wperm = getWritePermission();
            return new CursorToBulkCursorAdaptor(cursor, observer,
                    ContentProvider.this.getClass().getName(),
                    wperm == null ||
                    getContext().checkCallingOrSelfPermission(getWritePermission())
                            == PackageManager.PERMISSION_GRANTED,
                    window);
                    hasWritePermission(uri), window);
        }

        public Cursor query(Uri uri, String[] projection,
                String selection, String[] selectionArgs, String sortOrder) {
            checkReadPermission(uri);
            enforceReadPermission(uri);
            return ContentProvider.this.query(uri, projection, selection,
                    selectionArgs, sortOrder);
        }

        public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs,
                String sortOrder) {
            checkReadPermission(uri);
            enforceReadPermission(uri);
            return ContentProvider.this.queryEntities(uri, selection, selectionArgs, sortOrder);
        }

@@ -143,17 +143,17 @@ public abstract class ContentProvider implements ComponentCallbacks {


        public Uri insert(Uri uri, ContentValues initialValues) {
            checkWritePermission(uri);
            enforceWritePermission(uri);
            return ContentProvider.this.insert(uri, initialValues);
        }

        public int bulkInsert(Uri uri, ContentValues[] initialValues) {
            checkWritePermission(uri);
            enforceWritePermission(uri);
            return ContentProvider.this.bulkInsert(uri, initialValues);
        }

        public Uri insertEntity(Uri uri, Entity entities) {
            checkWritePermission(uri);
            enforceWritePermission(uri);
            return ContentProvider.this.insertEntity(uri, entities);
        }

@@ -161,55 +161,84 @@ public abstract class ContentProvider implements ComponentCallbacks {
                throws OperationApplicationException {
            for (ContentProviderOperation operation : operations) {
                if (operation.isReadOperation()) {
                    checkReadPermission(operation.getUri());
                    enforceReadPermission(operation.getUri());
                }

                if (operation.isWriteOperation()) {
                    checkWritePermission(operation.getUri());
                    enforceWritePermission(operation.getUri());
                }
            }
            return ContentProvider.this.applyBatch(operations);
        }

        public int delete(Uri uri, String selection, String[] selectionArgs) {
            checkWritePermission(uri);
            enforceWritePermission(uri);
            return ContentProvider.this.delete(uri, selection, selectionArgs);
        }

        public int update(Uri uri, ContentValues values, String selection,
                String[] selectionArgs) {
            checkWritePermission(uri);
            enforceWritePermission(uri);
            return ContentProvider.this.update(uri, values, selection, selectionArgs);
        }

        public int updateEntity(Uri uri, Entity entity) {
            checkWritePermission(uri);
            enforceWritePermission(uri);
            return ContentProvider.this.updateEntity(uri, entity);
        }

        public ParcelFileDescriptor openFile(Uri uri, String mode)
                throws FileNotFoundException {
            if (mode != null && mode.startsWith("rw")) checkWritePermission(uri);
            else checkReadPermission(uri);
            if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
            else enforceReadPermission(uri);
            return ContentProvider.this.openFile(uri, mode);
        }

        public AssetFileDescriptor openAssetFile(Uri uri, String mode)
                throws FileNotFoundException {
            if (mode != null && mode.startsWith("rw")) checkWritePermission(uri);
            else checkReadPermission(uri);
            if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
            else enforceReadPermission(uri);
            return ContentProvider.this.openAssetFile(uri, mode);
        }

        private void checkReadPermission(Uri uri) {
        private void enforceReadPermission(Uri uri) {
            final int uid = Binder.getCallingUid();
            if (uid == mMyUid) {
                return;
            }
            
            final Context context = getContext();
            final String rperm = getReadPermission();
            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();
            if (getContext().checkUriPermission(uri, rperm, null, pid, uid,
            if (rperm == null
                    || context.checkPermission(rperm, pid, uid)
                    == PackageManager.PERMISSION_GRANTED) {
                return;
            }
            
            PathPermission[] pps = getPathPermissions();
            if (pps != null) {
                final String path = uri.getPath();
                int i = pps.length;
                while (i > 0) {
                    i--;
                    final PathPermission pp = pps[i];
                    final String pprperm = pp.getReadPermission();
                    if (pprperm != null && pp.match(path)) {
                        if (context.checkPermission(pprperm, pid, uid)
                                == PackageManager.PERMISSION_GRANTED) {
                            return;
                        }
                    }
                }
            }
            
            if (context.checkUriPermission(uri, pid, uid,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION)
                    == PackageManager.PERMISSION_GRANTED) {
                return;
            }
            
            String msg = "Permission Denial: reading "
                    + ContentProvider.this.getClass().getName()
                    + " uri " + uri + " from pid=" + Binder.getCallingPid()
@@ -218,20 +247,57 @@ public abstract class ContentProvider implements ComponentCallbacks {
            throw new SecurityException(msg);
        }

        private void checkWritePermission(Uri uri) {
        private boolean hasWritePermission(Uri uri) {
            final int uid = Binder.getCallingUid();
            if (uid == mMyUid) {
                return true;
            }
            
            final Context context = getContext();
            final String wperm = getWritePermission();
            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();
            if (getContext().checkUriPermission(uri, null, wperm, pid, uid,
            if (wperm == null
                    || context.checkPermission(wperm, pid, uid)
                    == PackageManager.PERMISSION_GRANTED) {
                return true;
            }
            
            PathPermission[] pps = getPathPermissions();
            if (pps != null) {
                final String path = uri.getPath();
                int i = pps.length;
                while (i > 0) {
                    i--;
                    final PathPermission pp = pps[i];
                    final String ppwperm = pp.getWritePermission();
                    if (ppwperm != null && pp.match(path)) {
                        if (context.checkPermission(ppwperm, pid, uid)
                                == PackageManager.PERMISSION_GRANTED) {
                            return true;
                        }
                    }
                }
            }
            
            if (context.checkUriPermission(uri, pid, uid,
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                    == PackageManager.PERMISSION_GRANTED) {
                return true;
            }
            
            return false;
        }
        
        private void enforceWritePermission(Uri uri) {
            if (hasWritePermission(uri)) {
                return;
            }
            
            String msg = "Permission Denial: writing "
                    + ContentProvider.this.getClass().getName()
                    + " uri " + uri + " from pid=" + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid()
                    + " requires " + wperm;
                    + " requires " + getWritePermission();
            throw new SecurityException(msg);
        }
    }
@@ -290,6 +356,28 @@ public abstract class ContentProvider implements ComponentCallbacks {
        return mWritePermission;
    }

    /**
     * Change the path-based permission required to read and/or write data in
     * the content provider.  This is normally set for you from its manifest
     * information when the provider is first created.
     *
     * @param permissions Array of path permission descriptions.
     */
    protected final void setPathPermissions(PathPermission[] permissions) {
        mPathPermissions = permissions;
    }

    /**
     * Return the path-based permissions required for read and/or write access to
     * this content provider.  This method can be called from multiple
     * threads, as described in
     * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
     * Processes and Threads</a>.
     */
    public final PathPermission[] getPathPermissions() {
        return mPathPermissions;
    }

    /**
     * Called when the provider is being started.
     *
@@ -625,9 +713,11 @@ public abstract class ContentProvider implements ComponentCallbacks {
         */
        if (mContext == null) {
            mContext = context;
            mMyUid = Process.myUid();
            if (info != null) {
                setReadPermission(info.readPermission);
                setWritePermission(info.writePermission);
                setPathPermissions(info.pathPermissions);
            }
            ContentProvider.this.onCreate();
        }
+97 −1
Original line number Diff line number Diff line
@@ -1918,6 +1918,7 @@ public class PackageParser {
                        outInfo.metaData, outError)) == null) {
                    return false;
                }
                
            } else if (parser.getName().equals("grant-uri-permission")) {
                TypedArray sa = res.obtainAttributes(attrs,
                        com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
@@ -1956,6 +1957,101 @@ public class PackageParser {
                        outInfo.info.uriPermissionPatterns = newp;
                    }
                    outInfo.info.grantUriPermissions = true;
                } else {
                    if (!RIGID_PARSER) {
                        Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
                        Log.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>");
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
                    return false;
                }
                XmlUtils.skipCurrentTag(parser);

            } else if (parser.getName().equals("path-permission")) {
                TypedArray sa = res.obtainAttributes(attrs,
                        com.android.internal.R.styleable.AndroidManifestPathPermission);

                PathPermission pa = null;

                String permission = sa.getNonResourceString(
                        com.android.internal.R.styleable.AndroidManifestPathPermission_permission);
                String readPermission = sa.getNonResourceString(
                        com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission);
                if (readPermission == null) {
                    readPermission = permission;
                }
                String writePermission = sa.getNonResourceString(
                        com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission);
                if (writePermission == null) {
                    writePermission = permission;
                }
                
                boolean havePerm = false;
                if (readPermission != null) {
                    readPermission = readPermission.intern();
                    havePerm = true;
                }
                if (writePermission != null) {
                    writePermission = readPermission.intern();
                    havePerm = true;
                }

                if (!havePerm) {
                    if (!RIGID_PARSER) {
                        Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
                        Log.w(TAG, "No readPermission or writePermssion for <path-permission>");
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    outError[0] = "No readPermission or writePermssion for <path-permission>";
                    return false;
                }
                
                String path = sa.getNonResourceString(
                        com.android.internal.R.styleable.AndroidManifestPathPermission_path);
                if (path != null) {
                    pa = new PathPermission(path,
                            PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
                }

                path = sa.getNonResourceString(
                        com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix);
                if (path != null) {
                    pa = new PathPermission(path,
                            PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
                }

                path = sa.getNonResourceString(
                        com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern);
                if (path != null) {
                    pa = new PathPermission(path,
                            PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
                }

                sa.recycle();

                if (pa != null) {
                    if (outInfo.info.pathPermissions == null) {
                        outInfo.info.pathPermissions = new PathPermission[1];
                        outInfo.info.pathPermissions[0] = pa;
                    } else {
                        final int N = outInfo.info.pathPermissions.length;
                        PathPermission[] newp = new PathPermission[N+1];
                        System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
                        newp[N] = pa;
                        outInfo.info.pathPermissions = newp;
                    }
                } else {
                    if (!RIGID_PARSER) {
                        Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
                        Log.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>");
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                    outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
                    return false;
                }
                XmlUtils.skipCurrentTag(parser);

+68 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.content.pm;

import android.os.Parcel;
import android.os.Parcelable;
import android.os.PatternMatcher;

/**
 * Description of permissions needed to access a particular path
 * in a {@link ProviderInfo}.
 */
public class PathPermission extends PatternMatcher {
    private final String mReadPermission;
    private final String mWritePermission;
    
    public PathPermission(String pattern, int type, String readPermission,
            String writePermission) {
        super(pattern, type);
        mReadPermission = readPermission;
        mWritePermission = writePermission;
    }
    
    public String getReadPermission() {
        return mReadPermission;
    }
    
    public String getWritePermission() {
        return mWritePermission;
    }
    
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeString(mReadPermission);
        dest.writeString(mWritePermission);
    }
    
    public PathPermission(Parcel src) {
        super(src);
        mReadPermission = src.readString();
        mWritePermission = src.readString();
    }
    
    public static final Parcelable.Creator<PathPermission> CREATOR
            = new Parcelable.Creator<PathPermission>() {
        public PathPermission createFromParcel(Parcel source) {
            return new PathPermission(source);
        }

        public PathPermission[] newArray(int size) {
            return new PathPermission[size];
        }
    };
}
 No newline at end of file
+12 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.os.PatternMatcher;
 */
public final class ProviderInfo extends ComponentInfo
        implements Parcelable {
    
    /** The name provider is published under content:// */
    public String authority = null;
    
@@ -56,6 +57,14 @@ public final class ProviderInfo extends ComponentInfo
     */
    public PatternMatcher[] uriPermissionPatterns = null;
    
    /**
     * If non-null, these are path-specific permissions that are allowed for
     * accessing the provider.  Any permissions listed here will allow a
     * holding client to access the provider, and the provider will check
     * the URI it provides when making calls against the patterns here.
     */
    public PathPermission[] pathPermissions = null;
    
    /** If true, this content provider allows multiple instances of itself
     *  to run in different process.  If false, a single instances is always
     *  run in {@link #processName}. */
@@ -82,6 +91,7 @@ public final class ProviderInfo extends ComponentInfo
        writePermission = orig.writePermission;
        grantUriPermissions = orig.grantUriPermissions;
        uriPermissionPatterns = orig.uriPermissionPatterns;
        pathPermissions = orig.pathPermissions;
        multiprocess = orig.multiprocess;
        initOrder = orig.initOrder;
        isSyncable = orig.isSyncable;
@@ -98,6 +108,7 @@ public final class ProviderInfo extends ComponentInfo
        out.writeString(writePermission);
        out.writeInt(grantUriPermissions ? 1 : 0);
        out.writeTypedArray(uriPermissionPatterns, parcelableFlags);
        out.writeTypedArray(pathPermissions, parcelableFlags);
        out.writeInt(multiprocess ? 1 : 0);
        out.writeInt(initOrder);
        out.writeInt(isSyncable ? 1 : 0);
@@ -126,6 +137,7 @@ public final class ProviderInfo extends ComponentInfo
        writePermission = in.readString();
        grantUriPermissions = in.readInt() != 0;
        uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR);
        pathPermissions = in.createTypedArray(PathPermission.CREATOR);
        multiprocess = in.readInt() != 0;
        initOrder = in.readInt();
        isSyncable = in.readInt() != 0;
Loading