Merge "Improve documentation of onRequestPermissionsResult" into mnc-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index cbb1bb2..d1e19fb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -104,6 +104,7 @@
field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
field public static final java.lang.String HDMI_CEC = "android.permission.HDMI_CEC";
field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
+ field public static final java.lang.String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS";
field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
field public static final java.lang.String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES";
field public static final java.lang.String INSTALL_SHORTCUT = "com.android.launcher.permission.INSTALL_SHORTCUT";
@@ -181,6 +182,7 @@
field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
+ field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
@@ -9436,6 +9438,7 @@
method public void setAppIcon(android.graphics.Bitmap);
method public void setAppLabel(java.lang.CharSequence);
method public void setAppPackageName(java.lang.String);
+ method public void setGrantedRuntimePermissions(java.lang.String[]);
method public void setInstallLocation(int);
method public void setOriginatingUri(android.net.Uri);
method public void setReferrerUri(android.net.Uri);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e66da47..e782fb8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3982,16 +3982,24 @@
* as intermediaries that dispatch their intent to the target the user selects -- to
* do this, they must perform all security checks including permission grants as if
* their launch had come from the original activity.
+ * @param intent The Intent to start.
+ * @param options ActivityOptions or null.
+ * @param ignoreTargetSecurity If true, the activity manager will not check whether the
+ * caller it is doing the start is, is actually allowed to start the target activity.
+ * If you set this to true, you must set an explicit component in the Intent and do any
+ * appropriate security checks yourself.
+ * @param userId The user the new activity should run as.
* @hide
*/
- public void startActivityAsCaller(Intent intent, @Nullable Bundle options, int userId) {
+ public void startActivityAsCaller(Intent intent, @Nullable Bundle options,
+ boolean ignoreTargetSecurity, int userId) {
if (mParent != null) {
throw new RuntimeException("Can't be called from a child");
}
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivityAsCaller(
this, mMainThread.getApplicationThread(), mToken, this,
- intent, -1, options, userId);
+ intent, -1, options, ignoreTargetSecurity, userId);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, -1, ar.getResultCode(),
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index fc408a8..bfb92c4 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -206,9 +206,11 @@
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
+ boolean ignoreTargetSecurity = data.readInt() != 0;
int userId = data.readInt();
int result = startActivityAsCaller(app, callingPackage, intent, resolvedType,
- resultTo, resultWho, requestCode, startFlags, profilerInfo, options, userId);
+ resultTo, resultWho, requestCode, startFlags, profilerInfo, options,
+ ignoreTargetSecurity, userId);
reply.writeNoException();
reply.writeInt(result);
return true;
@@ -2675,7 +2677,8 @@
}
public int startActivityAsCaller(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException {
+ int startFlags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity,
+ int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -2699,6 +2702,7 @@
} else {
data.writeInt(0);
}
+ data.writeInt(ignoreTargetSecurity ? 1 : 0);
data.writeInt(userId);
mRemote.transact(START_ACTIVITY_AS_CALLER_TRANSACTION, data, reply, 0);
reply.readException();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 1d87d77..5eb3961 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -72,7 +72,8 @@
ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException;
public int startActivityAsCaller(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int flags, ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException;
+ int flags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity,
+ int userId) throws RemoteException;
public WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho,
int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options,
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 653f1b6..c2d901d 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1701,7 +1701,8 @@
*/
public ActivityResult execStartActivityAsCaller(
Context who, IBinder contextThread, IBinder token, Activity target,
- Intent intent, int requestCode, Bundle options, int userId) {
+ Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity,
+ int userId) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
@@ -1725,7 +1726,7 @@
.startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
- requestCode, 0, null, options, userId);
+ requestCode, 0, null, options, ignoreTargetSecurity, userId);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5571662..f786d2f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1023,7 +1023,7 @@
*
* <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#MNC MNC}
* and above and declares as using the {@link android.Manifest.permission#CALL_PHONE}
- * permission which is not granted, then atempting to use this action will
+ * permission which is not granted, then attempting to use this action will
* result in a {@link java.lang.SecurityException}.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index b7ee82d..9341be1 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -18,8 +18,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -889,6 +891,8 @@
public String abiOverride;
/** {@hide} */
public String volumeUuid;
+ /** {@hide} */
+ public String[] grantedRuntimePermissions;
/**
* Construct parameters for a new package install session.
@@ -914,6 +918,7 @@
referrerUri = source.readParcelable(null);
abiOverride = source.readString();
volumeUuid = source.readString();
+ grantedRuntimePermissions = source.readStringArray();
}
/**
@@ -987,6 +992,23 @@
this.referrerUri = referrerUri;
}
+ /**
+ * Sets which runtime permissions to be granted to the package at installation.
+ * Using this API requires holding {@link android.Manifest.permission
+ * #INSTALL_GRANT_RUNTIME_PERMISSIONS}
+ *
+ * @param permissions The permissions to grant or null to grant all runtime
+ * permissions.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)
+ public void setGrantedRuntimePermissions(String[] permissions) {
+ installFlags |= PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS;
+ this.grantedRuntimePermissions = permissions;
+ }
+
/** {@hide} */
public void setInstallFlagsInternal() {
installFlags |= PackageManager.INSTALL_INTERNAL;
@@ -1012,6 +1034,7 @@
pw.printPair("referrerUri", referrerUri);
pw.printPair("abiOverride", abiOverride);
pw.printPair("volumeUuid", volumeUuid);
+ pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
pw.println();
}
@@ -1033,6 +1056,7 @@
dest.writeParcelable(referrerUri, flags);
dest.writeString(abiOverride);
dest.writeString(volumeUuid);
+ dest.writeStringArray(grantedRuntimePermissions);
}
public static final Parcelable.Creator<SessionParams>
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 233bee3..39b66aa 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -103,7 +103,7 @@
|| ChooserActivity.class.getName().equals(ri.activityInfo.name));
try {
- startActivityAsCaller(newIntent, null, targetUserId);
+ startActivityAsCaller(newIntent, null, false, targetUserId);
} catch (RuntimeException e) {
int launchedFromUid = -1;
String launchedFromPackage = "?";
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7bc18f3..ba19131 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -973,7 +973,7 @@
@Override
public boolean startAsCaller(Activity activity, Bundle options, int userId) {
- activity.startActivityAsCaller(mResolvedIntent, options, userId);
+ activity.startActivityAsCaller(mResolvedIntent, options, false, userId);
return true;
}
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 32746c2..6393fba 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -20,6 +20,7 @@
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.net.Uri;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Base64;
import android.util.Xml;
@@ -45,6 +46,8 @@
/** {@hide} */
public class XmlUtils {
+ private static final String STRING_ARRAY_SEPARATOR = ":";
+
public static void skipCurrentTag(XmlPullParser parser)
throws XmlPullParserException, IOException {
int outerDepth = parser.getDepth();
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 062ae27..0c0ba7f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2052,10 +2052,24 @@
<permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
android:protectionLevel="signature|privileged" />
- <!-- @hide Allows an application to grant or revoke specific permissions. -->
- <permission android:name="android.permission.GRANT_REVOKE_PERMISSIONS"
+ <!-- Allows an application to grant specific permissions.
+ @hide -->
+ <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
android:protectionLevel="signature|installer" />
+ <!-- Allows an app that has this permission and the permissions to install packages
+ to request certain runtime permissions to be granted at installation.
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
+ android:protectionLevel="signature|installer|verifier" />
+
+ <!-- Allows an application to revoke specific permissions.
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
+ android:protectionLevel="signature|installer|verifier" />
+
<!-- @hide Allows an application to observe permission changes. -->
<permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
android:protectionLevel="signature|privileged" />
@@ -2539,12 +2553,6 @@
<permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE"
android:protectionLevel="signature" />
- <!-- Allows an app that has this permission and a permissions to install packages
- to request all runtime permissions to be granted at installation.
- @hide -->
- <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
- android:protectionLevel="signature" />
-
<!-- The system process that is allowed to bind to services in carrier apps will
have this permission. Carrier apps should use this permission to protect
their services that only the system is allowed to bind to.
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index 6a7930a..fd014eb 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -197,48 +197,36 @@
}
}
}
- if (spec.isDigestsSpecified()) {
- // Digest(s) explicitly specified in the spec
- mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
- if (mKeymasterDigest != -1) {
- // Key algorithm implies a digest -- ensure it's specified in the spec as
- // first digest.
- if (!com.android.internal.util.ArrayUtils.contains(
- mKeymasterDigests, mKeymasterDigest)) {
+
+ if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
+ // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
+ // implies SHA-256 digest). Because keymaster HMAC key is authorized only for
+ // one digest, we don't let algorithm parameter spec override the digest implied
+ // by the key. If the spec specifies digests at all, it must specify only one
+ // digest, the only implied by key algorithm.
+ mKeymasterDigests = new int[] {mKeymasterDigest};
+ if (spec.isDigestsSpecified()) {
+ // Digest(s) explicitly specified in the spec. Check that the list
+ // consists of exactly one digest, the one implied by key algorithm.
+ int[] keymasterDigestsFromSpec =
+ KeyProperties.Digest.allToKeymaster(spec.getDigests());
+ if ((keymasterDigestsFromSpec.length != 1)
+ || (keymasterDigestsFromSpec[0] != mKeymasterDigest)) {
throw new InvalidAlgorithmParameterException(
- "Digests specified in algorithm parameters ("
- + Arrays.asList(spec.getDigests()) + ") must include "
- + " the digest "
+ "Unsupported digests specification: "
+ + Arrays.asList(spec.getDigests()) + ". Only "
+ KeyProperties.Digest.fromKeymaster(mKeymasterDigest)
- + " implied by key algorithm");
- }
- if (mKeymasterDigests[0] != mKeymasterDigest) {
- // The first digest is not the one implied by the key algorithm.
- // Swap the implied digest with the first one.
- for (int i = 0; i < mKeymasterDigests.length; i++) {
- if (mKeymasterDigests[i] == mKeymasterDigest) {
- mKeymasterDigests[i] = mKeymasterDigests[0];
- mKeymasterDigests[0] = mKeymasterDigest;
- break;
- }
- }
+ + " supported for this HMAC key algorithm");
}
}
} else {
- // No digest specified in the spec
- if (mKeymasterDigest != -1) {
- // Key algorithm implies a digest -- use that digest
- mKeymasterDigests = new int[] {mKeymasterDigest};
+ // Key algorithm does not imply a digest.
+ if (spec.isDigestsSpecified()) {
+ mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
} else {
mKeymasterDigests = EmptyArray.INT;
}
}
- if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
- if (mKeymasterDigests.length == 0) {
- throw new InvalidAlgorithmParameterException(
- "At least one digest algorithm must be specified");
- }
- }
// Check that user authentication related parameters are acceptable. This method
// will throw an IllegalStateException if there are issues (e.g., secure lock screen
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index e9f19cd..88858de 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -41,6 +41,7 @@
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
+import java.security.ProviderException;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
@@ -605,50 +606,43 @@
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
int[] keymasterDigests;
- int keymasterDigest = KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
- if (params.isDigestsSpecified()) {
- // Digest(s) specified in parameters
- keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
- if (keymasterDigest != -1) {
- // Digest also specified in the JCA key algorithm name.
- if (!com.android.internal.util.ArrayUtils.contains(
- keymasterDigests, keymasterDigest)) {
- throw new KeyStoreException("Digest specified in key algorithm "
- + key.getAlgorithm() + " not specified in protection parameters: "
- + Arrays.asList(params.getDigests()));
- }
- // When the key is read back from keystore we reconstruct the JCA key algorithm
- // name from the KM_TAG_ALGORITHM and the first KM_TAG_DIGEST. Thus we need to
- // ensure that the digest reflected in the JCA key algorithm name is the first
- // KM_TAG_DIGEST tag.
- if (keymasterDigests[0] != keymasterDigest) {
- // The first digest is not the one implied by the JCA key algorithm name.
- // Swap the implied digest with the first one.
- for (int i = 0; i < keymasterDigests.length; i++) {
- if (keymasterDigests[i] == keymasterDigest) {
- keymasterDigests[i] = keymasterDigests[0];
- keymasterDigests[0] = keymasterDigest;
- break;
- }
- }
+ if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
+ // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
+ // implies SHA-256 digest). Because keymaster HMAC key is authorized only for one
+ // digest, we don't let import parameters override the digest implied by the key.
+ // If the parameters specify digests at all, they must specify only one digest, the
+ // only implied by key algorithm.
+ int keymasterImpliedDigest =
+ KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
+ if (keymasterImpliedDigest == -1) {
+ throw new ProviderException(
+ "HMAC key algorithm digest unknown for key algorithm "
+ + key.getAlgorithm());
+ }
+ keymasterDigests = new int[] {keymasterImpliedDigest};
+ if (params.isDigestsSpecified()) {
+ // Digest(s) explicitly specified in params -- check that the list consists of
+ // exactly one digest, the one implied by key algorithm.
+ int[] keymasterDigestsFromParams =
+ KeyProperties.Digest.allToKeymaster(params.getDigests());
+ if ((keymasterDigestsFromParams.length != 1)
+ || (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) {
+ throw new KeyStoreException(
+ "Unsupported digests specification: "
+ + Arrays.asList(params.getDigests()) + ". Only "
+ + KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest)
+ + " supported for HMAC key algorithm " + key.getAlgorithm());
}
}
} else {
- // No digest specified in parameters
- if (keymasterDigest != -1) {
- // Digest specified in the JCA key algorithm name.
- keymasterDigests = new int[] {keymasterDigest};
+ // Key algorithm does not imply a digest.
+ if (params.isDigestsSpecified()) {
+ keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
} else {
keymasterDigests = EmptyArray.INT;
}
}
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
- if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
- if (keymasterDigests.length == 0) {
- throw new KeyStoreException("At least one digest algorithm must be specified"
- + " for key algorithm " + key.getAlgorithm());
- }
- }
@KeyProperties.PurposeEnum int purposes = params.getPurposes();
int[] keymasterBlockModes =
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 919dd48..faaa1a6 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -642,7 +642,8 @@
* <p>This must be specified for signing/verification keys and RSA encryption/decryption
* keys used with RSA OAEP padding scheme because these operations involve a digest. For
* HMAC keys, the default is the digest associated with the key algorithm (e.g.,
- * {@code SHA-256} for key algorithm {@code HmacSHA256}).
+ * {@code SHA-256} for key algorithm {@code HmacSHA256}). HMAC keys cannot be authorized
+ * for more than one digest.
*
* <p>For private keys used for TLS/SSL client or server authentication it is usually
* necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 5b4b3e7..ec0ef24 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -423,7 +423,8 @@
* <p>This must be specified for signing/verification keys and RSA encryption/decryption
* keys used with RSA OAEP padding scheme because these operations involve a digest. For
* HMAC keys, the default is the digest specified in {@link Key#getAlgorithm()} (e.g.,
- * {@code SHA-256} for key algorithm {@code HmacSHA256}).
+ * {@code SHA-256} for key algorithm {@code HmacSHA256}). HMAC keys cannot be authorized
+ * for more than one digest.
*
* <p>For private keys used for TLS/SSL client or server authentication it is usually
* necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index eb520b4..b1a6844 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -263,10 +263,11 @@
bool ClipArea::rectangleModeClipRectWithTransform(const Rect& r,
const mat4* transform, SkRegion::Op op) {
- // TODO: we should be able to handle kReplace_Op efficiently without
- // going through RegionMode and later falling back into RectangleMode.
-
- if (op != SkRegion::kIntersect_Op) {
+ if (op == SkRegion::kReplace_Op && transform->rectToRect()) {
+ mClipRect = r;
+ transform->mapRect(mClipRect);
+ return true;
+ } else if (op != SkRegion::kIntersect_Op) {
enterRegionMode();
return regionModeClipRectWithTransform(r, transform, op);
}
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index e284af0..51ef27b 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -153,6 +153,8 @@
}
void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
+ // TODO: this should not mask every path to the viewport - this makes it impossible to use
+ // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
pathAsRegion.setPath(path, createViewportRegion());
}
diff --git a/libs/hwui/unit_tests/ClipAreaTests.cpp b/libs/hwui/unit_tests/ClipAreaTests.cpp
index 166d5b6..0c5e5e7 100644
--- a/libs/hwui/unit_tests/ClipAreaTests.cpp
+++ b/libs/hwui/unit_tests/ClipAreaTests.cpp
@@ -112,5 +112,16 @@
regionBounds.set(skRect);
EXPECT_EQ(expected, regionBounds);
}
+
+TEST(ClipArea, replaceNegative) {
+ ClipArea area(createClipArea());
+ area.setClip(0, 0, 100, 100);
+
+ Matrix4 transform;
+ transform.loadIdentity();
+ Rect expected(-50, -50, 50, 50);
+ area.clipRectWithTransform(expected, &transform, SkRegion::kReplace_Op);
+ EXPECT_EQ(expected, area.getClipRect());
+}
}
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 9832b45..c00fdf3 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -76,7 +76,9 @@
<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
<uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
<uses-permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" />
- <uses-permission android:name="android.permission.GRANT_REVOKE_PERMISSIONS" />
+ <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" />
+ <uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" />
+ <uses-permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.SET_KEYBOARD_LAYOUT" />
<uses-permission android:name="android.permission.GET_DETAILED_TASKS" />
<uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1582037..3bf6fde 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18,10 +18,7 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
-import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
-import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -3516,8 +3513,8 @@
intent.setComponent(new ComponentName(
ri.activityInfo.packageName, ri.activityInfo.name));
mStackSupervisor.startActivityLocked(null, intent, null, ri.activityInfo,
- null, null, null, null, 0, 0, 0, null, 0, 0, 0, null, false, null, null,
- null);
+ null, null, null, null, 0, 0, 0, null, 0, 0, 0, null, false, false,
+ null, null, null);
}
}
}
@@ -3803,13 +3800,14 @@
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- profilerInfo, null, null, options, userId, null, null);
+ profilerInfo, null, null, options, false, userId, null, null);
}
@Override
public final int startActivityAsCaller(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
+ int startFlags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity,
+ int userId) {
// This is very dangerous -- it allows you to perform a start activity (including
// permission grants) as any app that may launch one of your own activities. So
@@ -3843,6 +3841,16 @@
+ sourceRecord.launchedFromUid);
}
}
+ if (ignoreTargetSecurity) {
+ if (intent.getComponent() == null) {
+ throw new SecurityException(
+ "Component must be specified with ignoreTargetSecurity");
+ }
+ if (intent.getSelector() != null) {
+ throw new SecurityException(
+ "Selector not allowed with ignoreTargetSecurity");
+ }
+ }
targetUid = sourceRecord.launchedFromUid;
targetPackage = sourceRecord.launchedFromPackage;
}
@@ -3855,7 +3863,7 @@
try {
int ret = mStackSupervisor.startActivityMayWait(null, targetUid, targetPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, null,
- null, null, options, userId, null, null);
+ null, null, options, ignoreTargetSecurity, userId, null, null);
return ret;
} catch (SecurityException e) {
// XXX need to figure out how to propagate to original app.
@@ -3884,7 +3892,7 @@
// TODO: Switch to user app stacks here.
mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, res, null,
- options, userId, null, null);
+ options, false, userId, null, null);
return res;
}
@@ -3898,7 +3906,7 @@
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- null, null, config, options, userId, null, null);
+ null, null, config, options, false, userId, null, null);
return ret;
}
@@ -3956,7 +3964,7 @@
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(null, callingUid, callingPackage, intent,
resolvedType, session, interactor, null, null, 0, startFlags, profilerInfo, null,
- null, options, userId, null, null);
+ null, options, false, userId, null, null);
}
@Override
@@ -4067,7 +4075,7 @@
int res = mStackSupervisor.startActivityLocked(r.app.thread, intent,
r.resolvedType, aInfo, null, null, resultTo != null ? resultTo.appToken : null,
resultWho, requestCode, -1, r.launchedFromUid, r.launchedFromPackage,
- -1, r.launchedFromUid, 0, options, false, null, null, null);
+ -1, r.launchedFromUid, 0, options, false, false, null, null, null);
Binder.restoreCallingIdentity(origId);
r.finishing = wasFinishing;
@@ -4125,7 +4133,7 @@
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivityMayWait(null, uid, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- null, null, null, options, userId, container, inTask);
+ null, null, null, options, false, userId, container, inTask);
return ret;
}
@@ -20529,7 +20537,7 @@
}
return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,
resolvedType, null, null, null, null, 0, 0, null, null,
- null, options, callingUser, null, tr);
+ null, options, false, callingUser, null, tr);
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 470bbb0e..e57e3ff 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3117,7 +3117,7 @@
int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent,
null, aInfo, null, null, parent.appToken, null,
0, -1, parent.launchedFromUid, parent.launchedFromPackage,
- -1, parent.launchedFromUid, 0, null, true, null, null, null);
+ -1, parent.launchedFromUid, 0, null, false, true, null, null, null);
foundParentInTask = res == ActivityManager.START_SUCCESS;
} catch (RemoteException e) {
foundParentInTask = false;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c12aff6..05c58d7 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -911,7 +911,8 @@
null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */,
null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */,
null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */,
- 0 /* startFlags */, null /* options */, false /* componentSpecified */,
+ 0 /* startFlags */, null /* options */, false /* ignoreTargetSecurity */,
+ false /* componentSpecified */,
null /* outActivity */, null /* container */, null /* inTask */);
if (inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
@@ -926,7 +927,8 @@
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
- Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {
+ Bundle options, boolean ignoreTargetSecurity, int userId,
+ IActivityContainer iContainer, TaskRecord inTask) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -1043,7 +1045,7 @@
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
- realCallingPid, realCallingUid, startFlags, options,
+ realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
componentSpecified, null, container, inTask);
Binder.restoreCallingIdentity(origId);
@@ -1159,7 +1161,7 @@
int res = startActivityLocked(caller, intent, resolvedTypes[i],
aInfo, null, null, resultTo, null, -1, callingPid, callingUid,
callingPackage, callingPid, callingUid,
- 0, theseOptions, componentSpecified, outActivity, null, null);
+ 0, theseOptions, false, componentSpecified, outActivity, null, null);
if (res < 0) {
return res;
}
@@ -1400,8 +1402,8 @@
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
- boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,
- TaskRecord inTask) {
+ boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
+ ActivityContainer container, TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
@@ -1546,7 +1548,7 @@
if (startAnyPerm != PERMISSION_GRANTED) {
final int componentRestriction = getComponentRestrictionForCallingPackage(
- aInfo, callingPackage, callingPid, callingUid);
+ aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity);
final int actionRestriction = getActionRestrictionForCallingPackage(
intent.getAction(), callingPackage, callingPid, callingUid);
@@ -1675,13 +1677,13 @@
}
private int getComponentRestrictionForCallingPackage(ActivityInfo activityInfo,
- String callingPackage, int callingPid, int callingUid) {
+ String callingPackage, int callingPid, int callingUid, boolean ignoreTargetSecurity) {
if (activityInfo.permission == null) {
return ACTIVITY_RESTRICTION_NONE;
}
- if (mService.checkComponentPermission(activityInfo.permission, callingPid, callingUid,
- activityInfo.applicationInfo.uid, activityInfo.exported)
+ if (!ignoreTargetSecurity && mService.checkComponentPermission(activityInfo.permission,
+ callingPid, callingUid, activityInfo.applicationInfo.uid, activityInfo.exported)
== PackageManager.PERMISSION_DENIED) {
return ACTIVITY_RESTRICTION_PERMISSION;
}
@@ -1693,7 +1695,9 @@
if (mService.mAppOpsService.noteOperation(opCode, callingUid,
callingPackage) != AppOpsManager.MODE_ALLOWED) {
- return ACTIVITY_RESTRICTION_APPOP;
+ if (!ignoreTargetSecurity) {
+ return ACTIVITY_RESTRICTION_APPOP;
+ }
}
return ACTIVITY_RESTRICTION_NONE;
@@ -4296,7 +4300,7 @@
intent.addFlags(FORCE_NEW_TASK_FLAGS);
return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null,
- 0, 0, null, null, null, null, userId, this, null);
+ 0, 0, null, null, null, null, false, userId, this, null);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 2abd924..07de6f5 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -43,7 +43,6 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
-import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageInstaller;
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.IPackageInstallerSession;
@@ -71,7 +70,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
@@ -123,6 +121,7 @@
/** XML constants used in {@link #mSessionsFile} */
private static final String TAG_SESSIONS = "sessions";
private static final String TAG_SESSION = "session";
+ private static final String TAG_GRANTED_RUNTIME_PERMISSION = "granted-runtime-permission";
private static final String ATTR_SESSION_ID = "sessionId";
private static final String ATTR_USER_ID = "userId";
private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName";
@@ -144,6 +143,7 @@
private static final String ATTR_REFERRER_URI = "referrerUri";
private static final String ATTR_ABI_OVERRIDE = "abiOverride";
private static final String ATTR_VOLUME_UUID = "volumeUuid";
+ private static final String ATTR_NAME = "name";
/** Automatically destroy sessions older than this */
private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS;
@@ -374,16 +374,15 @@
}
} catch (FileNotFoundException e) {
// Missing sessions are okay, probably first boot
- } catch (IOException e) {
- Slog.wtf(TAG, "Failed reading install sessions", e);
- } catch (XmlPullParserException e) {
+ } catch (IOException | XmlPullParserException e) {
Slog.wtf(TAG, "Failed reading install sessions", e);
} finally {
IoUtils.closeQuietly(fis);
}
}
- private PackageInstallerSession readSessionLocked(XmlPullParser in) throws IOException {
+ private PackageInstallerSession readSessionLocked(XmlPullParser in) throws IOException,
+ XmlPullParserException {
final int sessionId = readIntAttribute(in, ATTR_SESSION_ID);
final int userId = readIntAttribute(in, ATTR_USER_ID);
final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME);
@@ -409,6 +408,7 @@
params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI);
params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE);
params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
+ params.grantedRuntimePermissions = readGrantedRuntimePermissions(in);
final File appIconFile = buildAppIconFile(sessionId);
if (appIconFile.exists()) {
@@ -501,9 +501,51 @@
params.appIconLastModified = appIconFile.lastModified();
}
+ writeGrantedRuntimePermissions(out, params.grantedRuntimePermissions);
+
out.endTag(null, TAG_SESSION);
}
+ private static void writeGrantedRuntimePermissions(XmlSerializer out,
+ String[] grantedRuntimePermissions) throws IOException {
+ if (grantedRuntimePermissions != null) {
+ for (String permission : grantedRuntimePermissions) {
+ out.startTag(null, TAG_GRANTED_RUNTIME_PERMISSION);
+ writeStringAttribute(out, ATTR_NAME, permission);
+ out.endTag(null, TAG_GRANTED_RUNTIME_PERMISSION);
+ }
+ }
+ }
+
+ private static String[] readGrantedRuntimePermissions(XmlPullParser in)
+ throws IOException, XmlPullParserException {
+ List<String> permissions = null;
+
+ final int outerDepth = in.getDepth();
+ int type;
+ while ((type = in.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || in.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ if (TAG_GRANTED_RUNTIME_PERMISSION.equals(in.getName())) {
+ String permission = readStringAttribute(in, ATTR_NAME);
+ if (permissions == null) {
+ permissions = new ArrayList<>();
+ }
+ permissions.add(permission);
+ }
+ }
+
+ if (permissions == null) {
+ return null;
+ }
+
+ String[] permissionsArray = new String[permissions.size()];
+ permissions.toArray(permissionsArray);
+ return permissionsArray;
+ }
+
private File buildAppIconFile(int sessionId) {
return new File(mSessionsDir, "app_icon." + sessionId + ".png");
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7602990..f041d50 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16,7 +16,6 @@
package com.android.server.pm;
-import static android.Manifest.permission.GRANT_REVOKE_PERMISSIONS;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
@@ -1339,8 +1338,8 @@
// permissions if requested before broadcasting the install.
if ((args.installFlags
& PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0) {
- grantRequestedRuntimePermissions(res.pkg,
- args.user.getIdentifier());
+ grantRequestedRuntimePermissions(res.pkg, args.user.getIdentifier(),
+ args.installGrantPermissions);
}
// Determine the set of users who are adding this
@@ -1669,12 +1668,17 @@
}
};
- private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int userId) {
+ private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int userId,
+ String[] grantedPermissions) {
if (userId >= UserHandle.USER_OWNER) {
- grantRequestedRuntimePermissionsForUser(pkg, userId);
+ grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions);
} else if (userId == UserHandle.USER_ALL) {
- for (int someUserId : UserManagerService.getInstance().getUserIds()) {
- grantRequestedRuntimePermissionsForUser(pkg, someUserId);
+ final int[] userIds;
+ synchronized (mPackages) {
+ userIds = UserManagerService.getInstance().getUserIds();
+ }
+ for (int someUserId : userIds) {
+ grantRequestedRuntimePermissionsForUser(pkg, someUserId, grantedPermissions);
}
}
@@ -1684,7 +1688,8 @@
}
}
- private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId) {
+ private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
+ String[] grantedPermissions) {
SettingBase sb = (SettingBase) pkg.mExtras;
if (sb == null) {
return;
@@ -1694,7 +1699,8 @@
for (String permission : pkg.requestedPermissions) {
BasePermission bp = mSettings.mPermissions.get(permission);
- if (bp != null && bp.isRuntime()) {
+ if (bp != null && bp.isRuntime() && (grantedPermissions == null
+ || ArrayUtils.contains(grantedPermissions, permission))) {
permissionsState.grantRuntimePermission(bp, userId);
}
}
@@ -3382,7 +3388,7 @@
}
mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
+ android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
"grantRuntimePermission");
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
@@ -3466,7 +3472,7 @@
}
mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
+ android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
"revokeRuntimePermission");
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
@@ -3517,7 +3523,7 @@
@Override
public void resetRuntimePermissions() {
mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
+ android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
"revokeRuntimePermission");
int callingUid = Binder.getCallingUid();
@@ -3527,16 +3533,19 @@
"resetRuntimePermissions");
}
- final int[] userIds;
-
synchronized (mPackages) {
updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL);
- final int userCount = UserManagerService.getInstance().getUserIds().length;
- userIds = Arrays.copyOf(UserManagerService.getInstance().getUserIds(), userCount);
- }
-
- for (int userId : userIds) {
- mDefaultPermissionPolicy.grantDefaultPermissions(userId);
+ for (int userId : UserManagerService.getInstance().getUserIds()) {
+ final int packageCount = mPackages.size();
+ for (int i = 0; i < packageCount; i++) {
+ PackageParser.Package pkg = mPackages.valueAt(i);
+ if (!(pkg.mExtras instanceof PackageSetting)) {
+ continue;
+ }
+ PackageSetting ps = (PackageSetting) pkg.mExtras;
+ resetUserChangesToRuntimePermissionsAndFlagsLocked(ps, userId);
+ }
+ }
}
}
@@ -3546,9 +3555,7 @@
return 0;
}
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
- "getPermissionFlags");
+ enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"getPermissionFlags");
@@ -3581,9 +3588,7 @@
return;
}
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
- "updatePermissionFlags");
+ enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"updatePermissionFlags");
@@ -3643,9 +3648,7 @@
return;
}
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
- "updatePermissionFlagsForAllApps");
+ enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlagsForAllApps");
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"updatePermissionFlagsForAllApps");
@@ -3675,6 +3678,17 @@
}
}
+ private void enforceGrantRevokeRuntimePermissionPermissions(String message) {
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
+ != PackageManager.PERMISSION_GRANTED
+ && mContext.checkCallingOrSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(message + " requires "
+ + Manifest.permission.GRANT_RUNTIME_PERMISSIONS + " or "
+ + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
+ }
+ }
+
@Override
public boolean shouldShowRequestPermissionRationale(String permissionName,
String packageName, int userId) {
@@ -9444,7 +9458,7 @@
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(origin, null, observer, installFlags, installerPackageName,
- null, verificationParams, user, packageAbiOverride);
+ null, verificationParams, user, packageAbiOverride, null);
mHandler.sendMessage(msg);
}
@@ -9464,7 +9478,8 @@
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(origin, null, observer, params.installFlags,
- installerPackageName, params.volumeUuid, verifParams, user, params.abiOverride);
+ installerPackageName, params.volumeUuid, verifParams, user, params.abiOverride,
+ params.grantedRuntimePermissions);
mHandler.sendMessage(msg);
}
@@ -10344,10 +10359,13 @@
private InstallArgs mArgs;
private int mRet;
final String packageAbiOverride;
+ final String[] grantedRuntimePermissions;
+
InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, String volumeUuid,
- VerificationParams verificationParams, UserHandle user, String packageAbiOverride) {
+ VerificationParams verificationParams, UserHandle user, String packageAbiOverride,
+ String[] grantedPermissions) {
super(user);
this.origin = origin;
this.move = move;
@@ -10357,6 +10375,7 @@
this.volumeUuid = volumeUuid;
this.verificationParams = verificationParams;
this.packageAbiOverride = packageAbiOverride;
+ this.grantedRuntimePermissions = grantedPermissions;
}
@Override
@@ -10786,6 +10805,7 @@
final ManifestDigest manifestDigest;
final UserHandle user;
final String abiOverride;
+ final String[] installGrantPermissions;
// The list of instruction sets supported by this app. This is currently
// only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -10795,7 +10815,7 @@
InstallArgs(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, String volumeUuid,
ManifestDigest manifestDigest, UserHandle user, String[] instructionSets,
- String abiOverride) {
+ String abiOverride, String[] installGrantPermissions) {
this.origin = origin;
this.move = move;
this.installFlags = installFlags;
@@ -10806,6 +10826,7 @@
this.user = user;
this.instructionSets = instructionSets;
this.abiOverride = abiOverride;
+ this.installGrantPermissions = installGrantPermissions;
}
abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
@@ -10898,7 +10919,8 @@
FileInstallArgs(InstallParams params) {
super(params.origin, params.move, params.observer, params.installFlags,
params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
- params.getUser(), null /* instruction sets */, params.packageAbiOverride);
+ params.getUser(), null /* instruction sets */, params.packageAbiOverride,
+ params.grantedRuntimePermissions);
if (isFwdLocked()) {
throw new IllegalArgumentException("Forward locking only supported in ASEC");
}
@@ -10907,7 +10929,7 @@
/** Existing install */
FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
super(OriginInfo.fromNothing(), null, null, 0, null, null, null, null, instructionSets,
- null);
+ null, null);
this.codeFile = (codePath != null) ? new File(codePath) : null;
this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
}
@@ -11123,7 +11145,8 @@
AsecInstallArgs(InstallParams params) {
super(params.origin, params.move, params.observer, params.installFlags,
params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
- params.getUser(), null /* instruction sets */, params.packageAbiOverride);
+ params.getUser(), null /* instruction sets */, params.packageAbiOverride,
+ params.grantedRuntimePermissions);
}
/** Existing install */
@@ -11131,7 +11154,7 @@
boolean isExternal, boolean isForwardLocked) {
super(OriginInfo.fromNothing(), null, null, (isExternal ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, null,
- instructionSets, null);
+ instructionSets, null, null);
// Hackily pretend we're still looking at a full code path
if (!fullCodePath.endsWith(RES_FILE_NAME)) {
fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath();
@@ -11148,7 +11171,7 @@
AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
super(OriginInfo.fromNothing(), null, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, null,
- instructionSets, null);
+ instructionSets, null, null);
this.cid = cid;
setMountPath(PackageHelper.getSdDir(cid));
}
@@ -11415,7 +11438,8 @@
MoveInstallArgs(InstallParams params) {
super(params.origin, params.move, params.observer, params.installFlags,
params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
- params.getUser(), null /* instruction sets */, params.packageAbiOverride);
+ params.getUser(), null /* instruction sets */, params.packageAbiOverride,
+ params.grantedRuntimePermissions);
}
int copyApk(IMediaContainerService imcs, boolean temp) {
@@ -15869,7 +15893,7 @@
final Message msg = mHandler.obtainMessage(INIT_COPY);
final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
msg.obj = new InstallParams(origin, move, installObserver, installFlags,
- installerPackageName, volumeUuid, null, user, packageAbiOverride);
+ installerPackageName, volumeUuid, null, user, packageAbiOverride, null);
mHandler.sendMessage(msg);
}
@@ -16036,7 +16060,9 @@
@Override
public void setPermissionEnforced(String permission, boolean enforced) {
- mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
+ // TODO: Now that we no longer change GID for storage, this should to away.
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+ "setPermissionEnforced");
if (READ_EXTERNAL_STORAGE.equals(permission)) {
synchronized (mPackages) {
if (mSettings.mReadExternalStorageEnforced == null
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 58fb088..bf78712 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -1050,6 +1050,7 @@
private int mConnectionCapabilities;
private VideoProvider mVideoProvider;
private boolean mAudioModeIsVoip;
+ private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED;
private StatusHints mStatusHints;
private int mVideoState;
private DisconnectCause mDisconnectCause;
@@ -1162,6 +1163,19 @@
}
/**
+ * Retrieves the connection start time of the {@code Connnection}, if specified. A value of
+ * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the
+ * start time of the conference.
+ *
+ * @return The time at which the {@code Connnection} was connected.
+ *
+ * @hide
+ */
+ public final long getConnectTimeMillis() {
+ return mConnectTimeMillis;
+ }
+
+ /**
* @return The status hints for this connection.
*/
public final StatusHints getStatusHints() {
@@ -1476,6 +1490,18 @@
}
/**
+ * Sets the time at which a call became active on this Connection. This is set only
+ * when a conference call becomes active on this connection.
+ *
+ * @param connectionTimeMillis The connection time, in milliseconds.
+ *
+ * @hide
+ */
+ public final void setConnectTimeMillis(long connectTimeMillis) {
+ mConnectTimeMillis = connectTimeMillis;
+ }
+
+ /**
* Sets the label and icon status to display in the in-call UI.
*
* @param statusHints The status label and icon to set.
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index d2e7a74..96f44b9 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -651,6 +651,7 @@
connection.getVideoState(),
connection.isRingbackRequested(),
connection.getAudioModeIsVoip(),
+ connection.getConnectTimeMillis(),
connection.getStatusHints(),
connection.getDisconnectCause(),
createIdList(connection.getConferenceables()),
@@ -979,6 +980,7 @@
connection.getVideoState(),
connection.isRingbackRequested(),
connection.getAudioModeIsVoip(),
+ connection.getConnectTimeMillis(),
connection.getStatusHints(),
connection.getDisconnectCause(),
emptyList,
diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java
index 683ab6a..fe0a4d8 100644
--- a/telecomm/java/android/telecom/ParcelableConnection.java
+++ b/telecomm/java/android/telecom/ParcelableConnection.java
@@ -44,6 +44,7 @@
private final int mVideoState;
private final boolean mRingbackRequested;
private final boolean mIsVoipAudioMode;
+ private final long mConnectTimeMillis;
private final StatusHints mStatusHints;
private final DisconnectCause mDisconnectCause;
private final List<String> mConferenceableConnectionIds;
@@ -62,6 +63,7 @@
int videoState,
boolean ringbackRequested,
boolean isVoipAudioMode,
+ long connectTimeMillis,
StatusHints statusHints,
DisconnectCause disconnectCause,
List<String> conferenceableConnectionIds,
@@ -77,6 +79,7 @@
mVideoState = videoState;
mRingbackRequested = ringbackRequested;
mIsVoipAudioMode = isVoipAudioMode;
+ mConnectTimeMillis = connectTimeMillis;
mStatusHints = statusHints;
mDisconnectCause = disconnectCause;
mConferenceableConnectionIds = conferenceableConnectionIds;
@@ -128,6 +131,10 @@
return mIsVoipAudioMode;
}
+ public long getConnectTimeMillis() {
+ return mConnectTimeMillis;
+ }
+
public final StatusHints getStatusHints() {
return mStatusHints;
}
@@ -176,6 +183,7 @@
int videoState = source.readInt();
boolean ringbackRequested = source.readByte() == 1;
boolean audioModeIsVoip = source.readByte() == 1;
+ long connectTimeMillis = source.readLong();
StatusHints statusHints = source.readParcelable(classLoader);
DisconnectCause disconnectCause = source.readParcelable(classLoader);
List<String> conferenceableConnectionIds = new ArrayList<>();
@@ -194,6 +202,7 @@
videoState,
ringbackRequested,
audioModeIsVoip,
+ connectTimeMillis,
statusHints,
disconnectCause,
conferenceableConnectionIds,
@@ -227,6 +236,7 @@
destination.writeInt(mVideoState);
destination.writeByte((byte) (mRingbackRequested ? 1 : 0));
destination.writeByte((byte) (mIsVoipAudioMode ? 1 : 0));
+ destination.writeLong(mConnectTimeMillis);
destination.writeParcelable(mStatusHints, 0);
destination.writeParcelable(mDisconnectCause, 0);
destination.writeStringList(mConferenceableConnectionIds);