diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-08-16 16:03:05 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-08-16 16:03:05 +0000 |
commit | dc701f2684a85bf6836e752ffac2d6badb55eb79 (patch) | |
tree | 2ceb1f27ab1afcc01a43cbdf39e07fba01b8e692 | |
parent | 641b3da47a5164698088dc9046ea56c026df891a (diff) | |
parent | 54f661b16b308cf38d1b9703214591c0f83df64d (diff) | |
download | base-dc701f2684a85bf6836e752ffac2d6badb55eb79.tar.gz |
Merge cherrypicks of [4793300, 4793320, 4793321, 4793340, 4793322, 4793061, 4793323, 4793324, 4793325, 4793380, 4793341, 4793342, 4793343, 4793265, 4793131, 4793132, 4793266, 4793133, 4793134, 4793400, 4793229, 4793381, 4793382, 4793383, 4793384, 4793385, 4793386, 4793387, 4793388, 4793062, 4793105, 4793063, 4793135, 4793389, 4793420] into pi-release
Change-Id: I5612c00adb30f4fc6c6d170f59b3533a5c8e58a2
7 files changed, 354 insertions, 65 deletions
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 6adae25fc38d..96cd043b8676 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -1748,7 +1748,8 @@ public final class SQLiteDatabase extends SQLiteClosable { executeSql(sql, bindArgs); } - private int executeSql(String sql, Object[] bindArgs) throws SQLException { + /** {@hide} */ + public int executeSql(String sql, Object[] bindArgs) throws SQLException { acquireReference(); try { final int statementType = DatabaseUtils.getSqlStatementType(sql); diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java index c6c676f81758..442e4cf0110c 100644 --- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java +++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java @@ -16,17 +16,25 @@ package android.database.sqlite; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.ContentValues; import android.database.Cursor; import android.database.DatabaseUtils; +import android.os.Build; import android.os.CancellationSignal; import android.os.OperationCanceledException; import android.provider.BaseColumns; import android.text.TextUtils; import android.util.Log; +import libcore.util.EmptyArray; + +import java.util.Arrays; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; @@ -95,9 +103,6 @@ public class SQLiteQueryBuilder if (mWhereClause == null) { mWhereClause = new StringBuilder(inWhere.length() + 16); } - if (mWhereClause.length() == 0) { - mWhereClause.append('('); - } mWhereClause.append(inWhere); } @@ -115,9 +120,6 @@ public class SQLiteQueryBuilder if (mWhereClause == null) { mWhereClause = new StringBuilder(inWhere.length() + 16); } - if (mWhereClause.length() == 0) { - mWhereClause.append('('); - } DatabaseUtils.appendEscapedSQLString(mWhereClause, inWhere); } @@ -376,6 +378,11 @@ public class SQLiteQueryBuilder return null; } + final String sql; + final String unwrappedSql = buildQuery( + projectionIn, selection, groupBy, having, + sortOrder, limit); + if (mStrict && selection != null && selection.length() > 0) { // Validate the user-supplied selection to detect syntactic anomalies // in the selection string that could indicate a SQL injection attempt. @@ -384,25 +391,167 @@ public class SQLiteQueryBuilder // originally specified. An attacker cannot create an expression that // would escape the SQL expression while maintaining balanced parentheses // in both the wrapped and original forms. - String sqlForValidation = buildQuery(projectionIn, "(" + selection + ")", groupBy, + + // NOTE: The ordering of the below operations is important; we must + // execute the wrapped query to ensure the untrusted clause has been + // fully isolated. + + // Validate the unwrapped query + db.validateSql(unwrappedSql, cancellationSignal); // will throw if query is invalid + + // Execute wrapped query for extra protection + final String wrappedSql = buildQuery(projectionIn, wrap(selection), groupBy, having, sortOrder, limit); - db.validateSql(sqlForValidation, cancellationSignal); // will throw if query is invalid + sql = wrappedSql; + } else { + // Execute unwrapped query + sql = unwrappedSql; } - String sql = buildQuery( - projectionIn, selection, groupBy, having, - sortOrder, limit); - + final String[] sqlArgs = selectionArgs; if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Performing query: " + sql); + if (Build.IS_DEBUGGABLE) { + Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs)); + } else { + Log.d(TAG, sql); + } } return db.rawQueryWithFactory( - mFactory, sql, selectionArgs, + mFactory, sql, sqlArgs, SQLiteDatabase.findEditTable(mTables), cancellationSignal); // will throw if query is invalid } /** + * Perform an update by combining all current settings and the + * information passed into this method. + * + * @param db the database to update on + * @param selection A filter declaring which rows to return, + * formatted as an SQL WHERE clause (excluding the WHERE + * itself). Passing null will return all rows for the given URL. + * @param selectionArgs You may include ?s in selection, which + * will be replaced by the values from selectionArgs, in order + * that they appear in the selection. The values will be bound + * as Strings. + * @return the number of rows updated + * @hide + */ + public int update(@NonNull SQLiteDatabase db, @NonNull ContentValues values, + @Nullable String selection, @Nullable String[] selectionArgs) { + Objects.requireNonNull(mTables, "No tables defined"); + Objects.requireNonNull(db, "No database defined"); + Objects.requireNonNull(values, "No values defined"); + + final String sql; + final String unwrappedSql = buildUpdate(values, selection); + + if (mStrict) { + // Validate the user-supplied selection to detect syntactic anomalies + // in the selection string that could indicate a SQL injection attempt. + // The idea is to ensure that the selection clause is a valid SQL expression + // by compiling it twice: once wrapped in parentheses and once as + // originally specified. An attacker cannot create an expression that + // would escape the SQL expression while maintaining balanced parentheses + // in both the wrapped and original forms. + + // NOTE: The ordering of the below operations is important; we must + // execute the wrapped query to ensure the untrusted clause has been + // fully isolated. + + // Validate the unwrapped query + db.validateSql(unwrappedSql, null); // will throw if query is invalid + + // Execute wrapped query for extra protection + final String wrappedSql = buildUpdate(values, wrap(selection)); + sql = wrappedSql; + } else { + // Execute unwrapped query + sql = unwrappedSql; + } + + if (selectionArgs == null) { + selectionArgs = EmptyArray.STRING; + } + final String[] rawKeys = values.keySet().toArray(EmptyArray.STRING); + final int valuesLength = rawKeys.length; + final Object[] sqlArgs = new Object[valuesLength + selectionArgs.length]; + for (int i = 0; i < sqlArgs.length; i++) { + if (i < valuesLength) { + sqlArgs[i] = values.get(rawKeys[i]); + } else { + sqlArgs[i] = selectionArgs[i - valuesLength]; + } + } + if (Log.isLoggable(TAG, Log.DEBUG)) { + if (Build.IS_DEBUGGABLE) { + Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs)); + } else { + Log.d(TAG, sql); + } + } + return db.executeSql(sql, sqlArgs); + } + + /** + * Perform a delete by combining all current settings and the + * information passed into this method. + * + * @param db the database to delete on + * @param selection A filter declaring which rows to return, + * formatted as an SQL WHERE clause (excluding the WHERE + * itself). Passing null will return all rows for the given URL. + * @param selectionArgs You may include ?s in selection, which + * will be replaced by the values from selectionArgs, in order + * that they appear in the selection. The values will be bound + * as Strings. + * @return the number of rows deleted + * @hide + */ + public int delete(@NonNull SQLiteDatabase db, @Nullable String selection, + @Nullable String[] selectionArgs) { + Objects.requireNonNull(mTables, "No tables defined"); + Objects.requireNonNull(db, "No database defined"); + + final String sql; + final String unwrappedSql = buildDelete(selection); + + if (mStrict) { + // Validate the user-supplied selection to detect syntactic anomalies + // in the selection string that could indicate a SQL injection attempt. + // The idea is to ensure that the selection clause is a valid SQL expression + // by compiling it twice: once wrapped in parentheses and once as + // originally specified. An attacker cannot create an expression that + // would escape the SQL expression while maintaining balanced parentheses + // in both the wrapped and original forms. + + // NOTE: The ordering of the below operations is important; we must + // execute the wrapped query to ensure the untrusted clause has been + // fully isolated. + + // Validate the unwrapped query + db.validateSql(unwrappedSql, null); // will throw if query is invalid + + // Execute wrapped query for extra protection + final String wrappedSql = buildDelete(wrap(selection)); + sql = wrappedSql; + } else { + // Execute unwrapped query + sql = unwrappedSql; + } + + final String[] sqlArgs = selectionArgs; + if (Log.isLoggable(TAG, Log.DEBUG)) { + if (Build.IS_DEBUGGABLE) { + Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs)); + } else { + Log.d(TAG, sql); + } + } + return db.executeSql(sql, sqlArgs); + } + + /** * Construct a SELECT statement suitable for use in a group of * SELECT statements that will be joined through UNION operators * in buildUnionQuery. @@ -434,28 +583,10 @@ public class SQLiteQueryBuilder String[] projectionIn, String selection, String groupBy, String having, String sortOrder, String limit) { String[] projection = computeProjection(projectionIn); - - StringBuilder where = new StringBuilder(); - boolean hasBaseWhereClause = mWhereClause != null && mWhereClause.length() > 0; - - if (hasBaseWhereClause) { - where.append(mWhereClause.toString()); - where.append(')'); - } - - // Tack on the user's selection, if present. - if (selection != null && selection.length() > 0) { - if (hasBaseWhereClause) { - where.append(" AND "); - } - - where.append('('); - where.append(selection); - where.append(')'); - } + String where = computeWhere(selection); return buildQueryString( - mDistinct, mTables, projection, where.toString(), + mDistinct, mTables, projection, where, groupBy, having, sortOrder, limit); } @@ -472,6 +603,42 @@ public class SQLiteQueryBuilder return buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit); } + /** {@hide} */ + public String buildUpdate(ContentValues values, String selection) { + if (values == null || values.size() == 0) { + throw new IllegalArgumentException("Empty values"); + } + + StringBuilder sql = new StringBuilder(120); + sql.append("UPDATE "); + sql.append(mTables); + sql.append(" SET "); + + final String[] rawKeys = values.keySet().toArray(EmptyArray.STRING); + for (int i = 0; i < rawKeys.length; i++) { + if (i > 0) { + sql.append(','); + } + sql.append(rawKeys[i]); + sql.append("=?"); + } + + final String where = computeWhere(selection); + appendClause(sql, " WHERE ", where); + return sql.toString(); + } + + /** {@hide} */ + public String buildDelete(String selection) { + StringBuilder sql = new StringBuilder(120); + sql.append("DELETE FROM "); + sql.append(mTables); + + final String where = computeWhere(selection); + appendClause(sql, " WHERE ", where); + return sql.toString(); + } + /** * Construct a SELECT statement suitable for use in a group of * SELECT statements that will be joined through UNION operators @@ -645,4 +812,37 @@ public class SQLiteQueryBuilder } return null; } + + private @Nullable String computeWhere(@Nullable String selection) { + final boolean hasInternal = !TextUtils.isEmpty(mWhereClause); + final boolean hasExternal = !TextUtils.isEmpty(selection); + + if (hasInternal || hasExternal) { + final StringBuilder where = new StringBuilder(); + if (hasInternal) { + where.append('(').append(mWhereClause).append(')'); + } + if (hasInternal && hasExternal) { + where.append(" AND "); + } + if (hasExternal) { + where.append('(').append(selection).append(')'); + } + return where.toString(); + } else { + return null; + } + } + + /** + * Wrap given argument in parenthesis, unless it's {@code null} or + * {@code ()}, in which case return it verbatim. + */ + private @Nullable String wrap(@Nullable String arg) { + if (TextUtils.isEmpty(arg)) { + return arg; + } else { + return "(" + arg + ")"; + } + } } diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 09af85db2620..c6f73cb47576 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -1583,7 +1583,8 @@ public abstract class Layout { } float get(final int offset) { - if (mHorizontals == null) { + if (mHorizontals == null || offset < mLineStartOffset + || offset >= mLineStartOffset + mHorizontals.length) { return getHorizontal(offset, mPrimary); } else { return mHorizontals[offset - mLineStartOffset]; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 692d6063fc02..bbd2ca4cb394 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9626,10 +9626,17 @@ public class ActivityManagerService extends IActivityManager.Stub } } - // If we're extending a persistable grant, then we always need to create - // the grant data structure so that take/release APIs work + // Figure out the value returned when access is allowed + final int allowedResult; if ((modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) { - return targetUid; + // If we're extending a persistable grant, then we need to return + // "targetUid" so that we always create a grant data structure to + // support take/release APIs + allowedResult = targetUid; + } else { + // Otherwise, we can return "-1" to indicate that no grant data + // structures need to be created + allowedResult = -1; } if (targetUid >= 0) { @@ -9638,7 +9645,7 @@ public class ActivityManagerService extends IActivityManager.Stub // No need to grant the target this permission. if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "Target " + targetPkg + " already has full permission to " + grantUri); - return -1; + return allowedResult; } } else { // First... there is no target package, so can anyone access it? @@ -9673,7 +9680,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (allowed) { - return -1; + return allowedResult; } } @@ -23039,6 +23046,7 @@ public class ActivityManagerService extends IActivityManager.Stub // The process is being computed, so there is a cycle. We cannot // rely on this process's state. app.containsCycle = true; + return false; } } @@ -23063,6 +23071,7 @@ public class ActivityManagerService extends IActivityManager.Stub final int logUid = mCurOomAdjUid; int prevAppAdj = app.curAdj; + int prevProcState = app.curProcState; if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) { // The max adjustment doesn't allow this app to be anything @@ -23541,11 +23550,16 @@ public class ActivityManagerService extends IActivityManager.Stub ProcessRecord client = cr.binding.client; computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now); if (client.containsCycle) { - // We've detected a cycle. We should ignore this connection and allow - // this process to retry computeOomAdjLocked later in case a later-checked - // connection from a client would raise its priority legitimately. + // We've detected a cycle. We should retry computeOomAdjLocked later in + // case a later-checked connection from a client would raise its + // priority legitimately. app.containsCycle = true; - continue; + // If the client has not been completely evaluated, skip using its + // priority. Else use the conservative value for now and look for a + // better state in the next iteration. + if (client.completedAdjSeq < mAdjSeq) { + continue; + } } int clientAdj = client.curRawAdj; int clientProcState = client.curProcState; @@ -23768,11 +23782,16 @@ public class ActivityManagerService extends IActivityManager.Stub } computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now); if (client.containsCycle) { - // We've detected a cycle. We should ignore this connection and allow - // this process to retry computeOomAdjLocked later in case a later-checked - // connection from a client would raise its priority legitimately. + // We've detected a cycle. We should retry computeOomAdjLocked later in + // case a later-checked connection from a client would raise its + // priority legitimately. app.containsCycle = true; - continue; + // If the client has not been completely evaluated, skip using its + // priority. Else use the conservative value for now and look for a + // better state in the next iteration. + if (client.completedAdjSeq < mAdjSeq) { + continue; + } } int clientAdj = client.curRawAdj; int clientProcState = client.curProcState; @@ -24004,8 +24023,8 @@ public class ActivityManagerService extends IActivityManager.Stub app.foregroundActivities = foregroundActivities; app.completedAdjSeq = mAdjSeq; - // if curAdj is less than prevAppAdj, then this process was promoted - return app.curAdj < prevAppAdj; + // if curAdj or curProcState improved, then this process was promoted + return app.curAdj < prevAppAdj || app.curProcState < prevProcState; } /** @@ -25058,7 +25077,7 @@ public class ActivityManagerService extends IActivityManager.Stub // - Continue retrying until no process was promoted. // - Iterate from least important to most important. int cycleCount = 0; - while (retryCycles) { + while (retryCycles && cycleCount < 10) { cycleCount++; retryCycles = false; @@ -25073,12 +25092,14 @@ public class ActivityManagerService extends IActivityManager.Stub for (int i=0; i<N; i++) { ProcessRecord app = mLruProcesses.get(i); if (!app.killedByAm && app.thread != null && app.containsCycle == true) { + if (computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now)) { retryCycles = true; } } } } + for (int i=N-1; i>=0; i--) { ProcessRecord app = mLruProcesses.get(i); if (!app.killedByAm && app.thread != null) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 9ed2b9c18546..6286a242dba2 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -12344,7 +12344,8 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r); } - mPermissionManager.removeAllPermissions(pkg, chatty); + final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet()); + mPermissionManager.removeAllPermissions(pkg, allPackageNames, mPermissionCallback, chatty); N = pkg.instrumentation.size(); r = null; diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java index a042fedf8b47..c3f23a81518a 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java @@ -115,7 +115,11 @@ public abstract class PermissionManagerInternal { */ public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty); public abstract void addAllPermissionGroups(@NonNull PackageParser.Package pkg, boolean chatty); - public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty); + public abstract void removeAllPermissions( + @NonNull PackageParser.Package pkg, + @NonNull List<String> allPackageNames, + @Nullable PermissionCallback permissionCallback, + boolean chatty); public abstract boolean addDynamicPermission(@NonNull PermissionInfo info, boolean async, int callingUid, @Nullable PermissionCallback callback); public abstract void removeDynamicPermission(@NonNull String permName, int callingUid, @@ -189,4 +193,4 @@ public abstract class PermissionManagerInternal { /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */ public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName); -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index c51a72406b53..02c9049f008e 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -30,6 +30,7 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageParser; @@ -37,6 +38,7 @@ import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.PackageParser.Package; import android.metrics.LogMaker; +import android.os.AsyncTask; import android.os.Binder; import android.os.Build; import android.os.Handler; @@ -455,8 +457,9 @@ public class PermissionManagerService { " to " + newPermissionGroupName); try { - revokeRuntimePermission(permissionName, packageName, false, - Process.SYSTEM_UID, userId, permissionCallback); + revokeRuntimePermission(permissionName, packageName, + mSettings.getPermission(permissionName), false, + Process.SYSTEM_UID, userId, permissionCallback, false); } catch (IllegalArgumentException e) { Slog.e(TAG, "Could not revoke " + permissionName + " from " + packageName, e); @@ -549,9 +552,59 @@ public class PermissionManagerService { } - private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) { + private void revokeAllPermissions( + @NonNull List<BasePermission> bps, + @NonNull List<String> allPackageNames, + @Nullable PermissionCallback permissionCallback) { + AsyncTask.execute(() -> { + final int numRemovedPermissions = bps.size(); + for (int permissionNum = 0; permissionNum < numRemovedPermissions; permissionNum++) { + final int[] userIds = mUserManagerInt.getUserIds(); + final int numUserIds = userIds.length; + + final int numPackages = allPackageNames.size(); + for (int packageNum = 0; packageNum < numPackages; packageNum++) { + final String packageName = allPackageNames.get(packageNum); + final ApplicationInfo applicationInfo = mPackageManagerInt.getApplicationInfo( + packageName, 0, Process.SYSTEM_UID, UserHandle.USER_SYSTEM); + if (applicationInfo != null + && applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + continue; + } + for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { + final int userId = userIds[userIdNum]; + final String permissionName = bps.get(permissionNum).getName(); + if (checkPermission(permissionName, packageName, UserHandle.USER_SYSTEM, + userId) == PackageManager.PERMISSION_GRANTED) { + try { + revokeRuntimePermission( + permissionName, + packageName, + bps.get(permissionNum), + false, + Process.SYSTEM_UID, + userId, + permissionCallback, + true); + } catch (IllegalArgumentException e) { + Slog.e(TAG, "Could not revoke " + permissionName + " from " + + packageName, e); + } + } + } + } + } + }); + } + + private void removeAllPermissions( + @NonNull PackageParser.Package pkg, + @NonNull List<String> allPackageNames, + @Nullable PermissionCallback permissionCallback, + boolean chatty) { synchronized (mLock) { int N = pkg.permissions.size(); + List<BasePermission> bps = new ArrayList<BasePermission>(N); StringBuilder r = null; for (int i=0; i<N; i++) { PackageParser.Permission p = pkg.permissions.get(i); @@ -560,6 +613,9 @@ public class PermissionManagerService { bp = mSettings.mPermissionTrees.get(p.info.name); } if (bp != null && bp.isPermission(p)) { + if ((p.info.getProtection() & PermissionInfo.PROTECTION_DANGEROUS) != 0) { + bps.add(bp); + } bp.setPermission(null); if (DEBUG_REMOVE && chatty) { if (r == null) { @@ -578,6 +634,7 @@ public class PermissionManagerService { } } } + revokeAllPermissions(bps, allPackageNames, permissionCallback); if (r != null) { if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r); } @@ -1490,9 +1547,10 @@ public class PermissionManagerService { } } - - private void revokeRuntimePermission(String permName, String packageName, - boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) { + + private void revokeRuntimePermission(String permName, String packageName, BasePermission bp, + boolean overridePolicy, int callingUid, int userId, PermissionCallback callback, + boolean permissionRemoved) { if (!mUserManagerInt.exists(userId)) { Log.e(TAG, "No such user:" + userId); return; @@ -1517,7 +1575,7 @@ public class PermissionManagerService { if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) { throw new IllegalArgumentException("Unknown package: " + packageName); } - final BasePermission bp = mSettings.getPermissionLocked(permName); + if (bp == null) { throw new IllegalArgumentException("Unknown permission: " + permName); } @@ -2073,8 +2131,10 @@ public class PermissionManagerService { PermissionManagerService.this.addAllPermissionGroups(pkg, chatty); } @Override - public void removeAllPermissions(Package pkg, boolean chatty) { - PermissionManagerService.this.removeAllPermissions(pkg, chatty); + public void removeAllPermissions(Package pkg, List<String> allPackageNames, + PermissionCallback permissionCallback, boolean chatty) { + PermissionManagerService.this.removeAllPermissions( + pkg, allPackageNames, permissionCallback, chatty); } @Override public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid, @@ -2110,7 +2170,8 @@ public class PermissionManagerService { boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) { PermissionManagerService.this.revokeRuntimePermission(permName, packageName, - overridePolicy, callingUid, userId, callback); + mSettings.getPermission(permName), overridePolicy, callingUid, userId, + callback, false); } @Override public void updatePermissions(String packageName, Package pkg, boolean replaceGrant, |