summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-08-16 16:41:35 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-08-16 16:41:35 +0000
commit841930e168bb956c79fd1aaedf0229e05f98fd5e (patch)
tree2ceb1f27ab1afcc01a43cbdf39e07fba01b8e692
parentcbaaaff2a1fed59a7bbb6d41a3b62d305a09feba (diff)
parent821e9bd5cc2be4b3210cb0226e40ba0f42b51aed (diff)
downloadbase-841930e168bb956c79fd1aaedf0229e05f98fd5e.tar.gz
Merge cherrypicks of [4793640, 4793602, 4793603, 4793660, 4793604, 4793680, 4793681, 4793581, 4793582, 4793625, 4793626, 4793627, 4793628, 4793700, 4793701, 4793702, 4793703, 4793704, 4793705, 4793661, 4793720, 4793721, 4793722, 4793723, 4793724, 4793725, 4793726, 4793727, 4793728, 4793583, 4793740, 4793760, 4793662, 4793780, 4793729] into pi-release-2
Change-Id: Ib2d16212f5099e42d971bfdaf8c260dbf0427889
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java3
-rw-r--r--core/java/android/database/sqlite/SQLiteQueryBuilder.java268
-rw-r--r--core/java/android/text/Layout.java3
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java53
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java3
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java81
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,