Merge "Prevent certain actions of app has revoked permissions" into mnc-dev
This commit is contained in:
@@ -1020,6 +1020,11 @@ public class Intent implements Parcelable, Cloneable {
|
||||
* <p>Note: this Intent <strong>cannot</strong> be used to call emergency
|
||||
* numbers. Applications can <strong>dial</strong> emergency numbers using
|
||||
* {@link #ACTION_DIAL}, however.
|
||||
*
|
||||
* <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
|
||||
* result in a {@link java.lang.SecurityException}.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public static final String ACTION_CALL = "android.intent.action.CALL";
|
||||
|
||||
@@ -283,7 +283,13 @@ public final class MediaStore {
|
||||
* supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
|
||||
* If you don't set a ClipData, it will be copied there for you when calling
|
||||
* {@link Context#startActivity(Intent)}.
|
||||
* @see #EXTRA_OUTPUT
|
||||
*
|
||||
* <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#CAMERA} permission which
|
||||
* is not granted, then atempting to use this action will result in a {@link
|
||||
* java.lang.SecurityException}.
|
||||
*
|
||||
* @see #EXTRA_OUTPUT
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
|
||||
@@ -331,6 +337,12 @@ public final class MediaStore {
|
||||
* supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
|
||||
* If you don't set a ClipData, it will be copied there for you when calling
|
||||
* {@link Context#startActivity(Intent)}.
|
||||
*
|
||||
* <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#CAMERA} permission which
|
||||
* is not granted, then atempting to use this action will result in a {@link
|
||||
* java.lang.SecurityException}.
|
||||
*
|
||||
* @see #EXTRA_OUTPUT
|
||||
* @see #EXTRA_VIDEO_QUALITY
|
||||
* @see #EXTRA_SIZE_LIMIT
|
||||
|
||||
@@ -25,7 +25,6 @@ import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
|
||||
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
|
||||
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static com.android.server.am.ActivityManagerDebugConfig.*;
|
||||
import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
|
||||
@@ -39,11 +38,13 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
|
||||
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
|
||||
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.StackInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.IActivityContainer;
|
||||
import android.app.IActivityContainerCallback;
|
||||
import android.app.IActivityManager;
|
||||
@@ -62,6 +63,7 @@ import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Configuration;
|
||||
@@ -90,9 +92,11 @@ import android.os.SystemClock;
|
||||
import android.os.TransactionTooLargeException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.WorkSource;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.SettingNotFoundException;
|
||||
import android.service.voice.IVoiceInteractionSession;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.EventLog;
|
||||
import android.util.Slog;
|
||||
@@ -108,6 +112,7 @@ import com.android.internal.app.IVoiceInteractor;
|
||||
import com.android.internal.content.ReferrerIntent;
|
||||
import com.android.internal.os.TransferPipe;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.am.ActivityStack.ActivityState;
|
||||
@@ -170,6 +175,25 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
||||
|
||||
private static final String LOCK_TASK_TAG = "Lock-to-App";
|
||||
|
||||
// Activity actions an app cannot start if it uses a permission which is not granted.
|
||||
private static final ArrayMap<String, String> ACTION_TO_RUNTIME_PERMISSION =
|
||||
new ArrayMap<>();
|
||||
static {
|
||||
ACTION_TO_RUNTIME_PERMISSION.put(MediaStore.ACTION_IMAGE_CAPTURE,
|
||||
Manifest.permission.CAMERA);
|
||||
ACTION_TO_RUNTIME_PERMISSION.put(MediaStore.ACTION_VIDEO_CAPTURE,
|
||||
Manifest.permission.CAMERA);
|
||||
ACTION_TO_RUNTIME_PERMISSION.put(Intent.ACTION_CALL,
|
||||
Manifest.permission.CALL_PHONE);
|
||||
}
|
||||
|
||||
/** Action not restricted for the calling package. */
|
||||
private static final int ACTION_RESTRICTION_NONE = 0;
|
||||
/** Action restricted for the calling package by not granting a used permission. */
|
||||
private static final int ACTION_RESTRICTION_PERMISSION = 1;
|
||||
/** Action restricted for the calling package by not allowing a used permission's app op. */
|
||||
private static final int ACTION_RESTRICTION_APPOP = 2;
|
||||
|
||||
/** Status Bar Service **/
|
||||
private IBinder mToken = new Binder();
|
||||
private IStatusBarService mStatusBarService;
|
||||
@@ -1519,14 +1543,23 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
||||
START_ANY_ACTIVITY, callingPid, callingUid);
|
||||
final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
|
||||
callingUid, aInfo.applicationInfo.uid, aInfo.exported);
|
||||
if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
|
||||
final int actionRestriction = getActionRestrictionForCallingPackage(
|
||||
intent.getAction(), callingPackage, callingPid, callingUid);
|
||||
|
||||
if (startAnyPerm != PERMISSION_GRANTED && (componentPerm != PERMISSION_GRANTED
|
||||
|| actionRestriction == ACTION_RESTRICTION_PERMISSION)) {
|
||||
if (resultRecord != null) {
|
||||
resultStack.sendActivityResultLocked(-1,
|
||||
resultRecord, resultWho, requestCode,
|
||||
Activity.RESULT_CANCELED, null);
|
||||
}
|
||||
String msg;
|
||||
if (!aInfo.exported) {
|
||||
if (actionRestriction == ACTION_RESTRICTION_PERMISSION) {
|
||||
msg = "Permission Denial: starting " + intent.toString()
|
||||
+ " from " + callerApp + " (pid=" + callingPid
|
||||
+ ", uid=" + callingUid + ")" + " with revoked permission "
|
||||
+ ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
|
||||
} else if (!aInfo.exported) {
|
||||
msg = "Permission Denial: starting " + intent.toString()
|
||||
+ " from " + callerApp + " (pid=" + callingPid
|
||||
+ ", uid=" + callingUid + ")"
|
||||
@@ -1541,7 +1574,19 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
||||
throw new SecurityException(msg);
|
||||
}
|
||||
|
||||
boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
|
||||
boolean abort = false;
|
||||
|
||||
if (startAnyPerm != PERMISSION_GRANTED
|
||||
&& actionRestriction == ACTION_RESTRICTION_APPOP) {
|
||||
String msg = "Permission Denial: starting " + intent.toString()
|
||||
+ " from " + callerApp + " (pid=" + callingPid
|
||||
+ ", uid=" + callingUid + ")"
|
||||
+ " requires " + aInfo.permission;
|
||||
Slog.w(TAG, msg);
|
||||
abort = true;
|
||||
}
|
||||
|
||||
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
|
||||
callingPid, resolvedType, aInfo.applicationInfo);
|
||||
|
||||
if (mService.mController != null) {
|
||||
@@ -1619,6 +1664,48 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
||||
return err;
|
||||
}
|
||||
|
||||
private int getActionRestrictionForCallingPackage(String action,
|
||||
String callingPackage, int callingPid, int callingUid) {
|
||||
if (action == null) {
|
||||
return ACTION_RESTRICTION_NONE;
|
||||
}
|
||||
|
||||
String permission = ACTION_TO_RUNTIME_PERMISSION.get(action);
|
||||
if (permission == null) {
|
||||
return ACTION_RESTRICTION_NONE;
|
||||
}
|
||||
|
||||
final PackageInfo packageInfo;
|
||||
try {
|
||||
packageInfo = mService.mContext.getPackageManager()
|
||||
.getPackageInfo(callingPackage, PackageManager.GET_PERMISSIONS);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.i(TAG, "Cannot find package info for " + callingPackage);
|
||||
return ACTION_RESTRICTION_NONE;
|
||||
}
|
||||
|
||||
if (!ArrayUtils.contains(packageInfo.requestedPermissions, permission)) {
|
||||
return ACTION_RESTRICTION_NONE;
|
||||
}
|
||||
|
||||
if (mService.checkPermission(permission, callingPid, callingUid) ==
|
||||
PackageManager.PERMISSION_DENIED) {
|
||||
return ACTION_RESTRICTION_PERMISSION;
|
||||
}
|
||||
|
||||
final int opCode = AppOpsManager.permissionToOpCode(permission);
|
||||
if (opCode == AppOpsManager.OP_NONE) {
|
||||
return ACTION_RESTRICTION_NONE;
|
||||
}
|
||||
|
||||
if (mService.mAppOpsService.noteOperation(opCode, callingUid,
|
||||
callingPackage) != AppOpsManager.MODE_ALLOWED) {
|
||||
return ACTION_RESTRICTION_APPOP;
|
||||
}
|
||||
|
||||
return ACTION_RESTRICTION_NONE;
|
||||
}
|
||||
|
||||
ActivityStack computeStackFocus(ActivityRecord r, boolean newTask) {
|
||||
final TaskRecord task = r.task;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user