summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvet Ganov <svetoslavganov@google.com>2015-03-17 10:56:51 -0700
committerSvetoslav Ganov <svetoslavganov@google.com>2015-03-24 01:53:30 +0000
commit3c99a2b334eb00b6cfa078a9e9ed2d6a151bde46 (patch)
tree3739cecedee62ffe5539c8af1e4eef536528f13d
parente368d1407e49aebdee511d9c2ccd8666440fd914 (diff)
downloadandroid_packages_apps_PackageInstaller-3c99a2b334eb00b6cfa078a9e9ed2d6a151bde46.tar.gz
android_packages_apps_PackageInstaller-3c99a2b334eb00b6cfa078a9e9ed2d6a151bde46.tar.bz2
android_packages_apps_PackageInstaller-3c99a2b334eb00b6cfa078a9e9ed2d6a151bde46.zip
Add basic support for new runtime permissions
Change-Id: I7ec15992587b0036030386be35eedc095055b6eb
-rw-r--r--AndroidManifest.xml2
-rw-r--r--res/layout/install_start.xml2
-rw-r--r--src/com/android/packageinstaller/GrantActivity.java238
3 files changed, 130 insertions, 112 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5cb5720a..781d60b3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -67,7 +67,7 @@
android:excludeFromRecents="true"
android:theme="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
<intent-filter>
- <action android:name="android.content.pm.action.REQUEST_PERMISSION" />
+ <action android:name="android.content.pm.action.REQUEST_PERMISSIONS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
diff --git a/res/layout/install_start.xml b/res/layout/install_start.xml
index 5e0f9579..9acf1992 100644
--- a/res/layout/install_start.xml
+++ b/res/layout/install_start.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/src/com/android/packageinstaller/GrantActivity.java b/src/com/android/packageinstaller/GrantActivity.java
index a3f7f5c9..3664fc00 100644
--- a/src/com/android/packageinstaller/GrantActivity.java
+++ b/src/com/android/packageinstaller/GrantActivity.java
@@ -18,12 +18,16 @@ package com.android.packageinstaller;
import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionInfo;
import android.os.Bundle;
+import android.os.UserHandle;
import android.support.v4.view.ViewPager;
+import android.util.Slog;
+import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -33,66 +37,111 @@ import android.widget.Button;
import android.widget.TabHost;
import android.widget.TextView;
-import java.util.ArrayList;
-import java.util.List;
-
/*
* The activity which is responsible for asking the user to grant permissions
* to applications.
*/
public class GrantActivity extends Activity implements OnClickListener {
- private Button mOk;
- private Button mCancel;
+ private static final String LOG_TAG = "GrantActivity";
+
+ private static final int PERMISSION_GRANTED = 1;
+ private static final int PERMISSION_DENIED = 2;
+ private static final int PERMISSION_DENIED_RUNTIME = 3;
+
+ private String[] mRequestedPermissions;
+ private int[] mGrantResults;
+ private final SparseArray<String> mRequestedRuntimePermissions = new SparseArray<>();
+
private PackageManager mPm;
- private String mRequestingPackage;
- private String[] requested_permissions;
+
+ private Button mOk;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+
mPm = getPackageManager();
- mRequestingPackage = this.getCallingPackage();
- requested_permissions = getRequestedPermissions();
- if (requested_permissions.length == 0) {
- // The grant request was empty. Return success
- setResult(RESULT_OK);
- finish();
+ mRequestedPermissions = getIntent().getStringArrayExtra(
+ PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES);
+ if (mRequestedPermissions == null) {
+ mRequestedPermissions = new String[0];
+ }
+
+ mGrantResults = new int[mRequestedPermissions.length];
+
+ final int requestedPermCount = mRequestedPermissions.length;
+ if (requestedPermCount == 0) {
+ setResultAndFinish();
return;
}
+ for (int i = 0; i < requestedPermCount; i++) {
+ String permission = mRequestedPermissions[i];
+ final int state = computePermissionGrantState(permission);
+ switch (state) {
+ case PERMISSION_GRANTED: {
+ mGrantResults[i] = PackageManager.PERMISSION_GRANTED;
+ } break;
+
+ case PERMISSION_DENIED: {
+ mGrantResults[i] = PackageManager.PERMISSION_DENIED;
+ } break;
+
+ case PERMISSION_DENIED_RUNTIME: {
+ mGrantResults[i] = PackageManager.PERMISSION_DENIED;
+ mRequestedRuntimePermissions.put(i, permission);
+ } break;
+ }
+ }
+
PackageInfo pkgInfo = getUpdatedPackageInfo();
AppSecurityPermissions perms = new AppSecurityPermissions(this, pkgInfo);
+
if (perms.getPermissionCount(AppSecurityPermissions.WHICH_NEW) == 0) {
- // The updated permissions dialog said there are no new permissions.
- // This should never occur if requested_permissions.length > 0,
- // but we check for it anyway, just in case.
- setResult(RESULT_OK);
- finish();
+ setResultAndFinish();
return;
}
setContentView(R.layout.install_start);
- ((TextView)findViewById(R.id.install_confirm_question)).setText(R.string.grant_confirm_question);
- PackageUtil.AppSnippet as = new PackageUtil.AppSnippet(mPm.getApplicationLabel(pkgInfo.applicationInfo),
+ bindUi(pkgInfo, perms);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == mOk) {
+ grantRequestedPermissions();
+ }
+ setResultAndFinish();
+ }
+
+ private void bindUi(PackageInfo pkgInfo, AppSecurityPermissions perms) {
+ TextView confirmMessage = (TextView)findViewById(R.id.install_confirm_question);
+ confirmMessage.setText(R.string.grant_confirm_question);
+
+ PackageUtil.AppSnippet as = new PackageUtil.AppSnippet(
+ mPm.getApplicationLabel(pkgInfo.applicationInfo),
mPm.getApplicationIcon(pkgInfo.applicationInfo));
PackageUtil.initSnippetForNewApp(this, as, R.id.app_snippet);
- mOk = (Button)findViewById(R.id.ok_button);
+
+ mOk = (Button) findViewById(R.id.ok_button);
mOk.setText(R.string.ok);
- mCancel = (Button)findViewById(R.id.cancel_button);
mOk.setOnClickListener(this);
- mCancel.setOnClickListener(this);
+
+ Button cancel = (Button) findViewById(R.id.cancel_button);
+ cancel.setOnClickListener(this);
TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost);
tabHost.setup();
+
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
TabsAdapter adapter = new TabsAdapter(this, tabHost, viewPager);
View newTab = perms.getPermissionsView(AppSecurityPermissions.WHICH_NEW);
- View allTab = getPermissionList(perms);
-
adapter.addTab(tabHost.newTabSpec("new").setIndicator(
getText(R.string.newPerms)), newTab);
+
+ View allTab = getPermissionList(perms);
adapter.addTab(tabHost.newTabSpec("all").setIndicator(
getText(R.string.allPerms)), allTab);
}
@@ -104,15 +153,19 @@ public class GrantActivity extends Activity implements OnClickListener {
*/
private PackageInfo getUpdatedPackageInfo() {
try {
- PackageInfo pkgInfo = mPm.getPackageInfo(mRequestingPackage, PackageManager.GET_PERMISSIONS);
+ PackageInfo pkgInfo = mPm.getPackageInfo(getCallingPackage(),
+ PackageManager.GET_PERMISSIONS);
for (int i = 0; i < pkgInfo.requestedPermissions.length; i++) {
- for (String requested_permission : requested_permissions) {
- if (requested_permission.equals(pkgInfo.requestedPermissions[i])) {
- pkgInfo.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
+ String requestedPerm = pkgInfo.requestedPermissions[i];
+ final int notGrantedCount = mRequestedRuntimePermissions.size();
+ for (int j = 0; j < notGrantedCount; j++) {
+ String notGrantedPerm = mRequestedRuntimePermissions.get(j);
+ if (requestedPerm.equals(notGrantedPerm)) {
+ pkgInfo.requestedPermissionsFlags[i]
+ |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
}
}
}
-
return pkgInfo;
} catch (NameNotFoundException e) {
throw new RuntimeException(e); // will never occur
@@ -131,99 +184,64 @@ public class GrantActivity extends Activity implements OnClickListener {
return root;
}
- /**
- * Return an array of permissions requested by the caller, filtered to exclude
- * irrelevant or otherwise malicious permission requests from untrusted callers.
- */
- private String[] getRequestedPermissions() {
- String[] permissions = getIntent()
- .getStringArrayExtra(PackageManager.EXTRA_REQUEST_PERMISSION_PERMISSION_LIST);
- if (permissions == null) {
- return new String[0];
- }
- permissions = keepNormalDangerousPermissions(permissions);
- permissions = keepRequestingPackagePermissions(permissions);
- return permissions;
-
- }
-
- /**
- * Remove any permissions in {@code permissions} which are not present
- * in {@code mRequestingPackage} and return the result. We also filter out
- * permissions which are required by {@code mRequestingPackage}, and permissions
- * which have already been granted to {@code mRequestingPackage}, as those permissions
- * are useless to change.
- */
- private String[] keepRequestingPackagePermissions(String[] permissions) {
- List<String> result = new ArrayList<String>();
+ private int computePermissionGrantState(String permission) {
+ final PackageInfo pkgInfo;
try {
- PackageInfo pkgInfo = mPm.getPackageInfo(mRequestingPackage, PackageManager.GET_PERMISSIONS);
+ pkgInfo = getPackageManager().getPackageInfo(getCallingPackage(),
+ PackageManager.GET_PERMISSIONS);
if (pkgInfo.requestedPermissions == null) {
- return new String[0];
- }
- for (int i = 0; i < pkgInfo.requestedPermissions.length; i++) {
- for (String permission : permissions) {
- final boolean isRequired =
- ((pkgInfo.requestedPermissionsFlags[i]
- & PackageInfo.REQUESTED_PERMISSION_REQUIRED) != 0);
- final boolean isGranted =
- ((pkgInfo.requestedPermissionsFlags[i]
- & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0);
-
- /*
- * We ignore required permissions, and permissions which have already
- * been granted, as it's useless to grant those permissions.
- */
- if (permission.equals(pkgInfo.requestedPermissions[i])
- && !isRequired && !isGranted) {
- result.add(permission);
- break;
- }
- }
+ return PERMISSION_DENIED;
}
} catch (NameNotFoundException e) {
- throw new RuntimeException(e); // should never happen
+ Slog.i(LOG_TAG, "No such permission:" + permission, e);
+ return PERMISSION_DENIED;
}
- return result.toArray(new String[result.size()]);
- }
- /**
- * Filter the permissions in {@code permissions}, keeping only the NORMAL or DANGEROUS
- * permissions.
- *
- * @param permissions the permissions to filter
- * @return A subset of {@code permissions} with only the
- * NORMAL or DANGEROUS permissions kept
- */
- private String[] keepNormalDangerousPermissions(String[] permissions) {
- List<String> result = new ArrayList<String>();
- for (String permission : permissions) {
- try {
- PermissionInfo pInfo = mPm.getPermissionInfo(permission, 0);
- final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
- if ((base != PermissionInfo.PROTECTION_NORMAL)
- && (base != PermissionInfo.PROTECTION_DANGEROUS)) {
- continue;
+ boolean permissionRequested = false;
+
+ for (int i = 0; i < pkgInfo.requestedPermissions.length; i++) {
+ if (permission.equals(pkgInfo.requestedPermissions[i])) {
+ permissionRequested = true;
+ if ((pkgInfo.requestedPermissionsFlags[i]
+ & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
+ return PERMISSION_GRANTED;
}
- result.add(permission);
- } catch (NameNotFoundException e) {
- // ignore
+ break;
}
}
- return result.toArray(new String[result.size()]);
- }
- @Override
- public void onClick(View v) {
- if (v == mOk) {
- for (String permission : requested_permissions) {
- mPm.grantPermission(mRequestingPackage, permission);
+ if (!permissionRequested) {
+ return PERMISSION_DENIED;
+ }
+
+ try {
+ PermissionInfo pInfo = mPm.getPermissionInfo(permission, 0);
+ if ((pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+ != PermissionInfo.PROTECTION_DANGEROUS) {
+ return PERMISSION_DENIED;
}
- setResult(RESULT_OK);
+ } catch (NameNotFoundException e) {
+ /* ignore */
}
- if (v == mCancel) {
- setResult(RESULT_CANCELED);
+
+ return PERMISSION_DENIED_RUNTIME;
+ }
+
+ private void grantRequestedPermissions() {
+ final int requestedPermCount = mRequestedRuntimePermissions.size();
+ for (int i = 0; i < requestedPermCount; i++) {
+ String permission = mRequestedRuntimePermissions.valueAt(i);
+ mPm.grantPermission(getCallingPackage(), permission, new UserHandle(getUserId()));
+ final int index = mRequestedRuntimePermissions.keyAt(i);
+ mGrantResults[index] = PackageManager.PERMISSION_GRANTED;
}
+ }
+
+ private void setResultAndFinish() {
+ Intent result = new Intent(PackageManager.ACTION_REQUEST_PERMISSIONS);
+ result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, mRequestedPermissions);
+ result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS, mGrantResults);
+ setResult(RESULT_OK, result);
finish();
}
}