diff options
-rw-r--r-- | AndroidManifest.xml | 2 | ||||
-rw-r--r-- | res/layout/install_start.xml | 2 | ||||
-rw-r--r-- | src/com/android/packageinstaller/GrantActivity.java | 238 |
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(); } } |