From f48236deb98e2a7b2fccd9458af29d03d2364111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 20 May 2015 18:26:58 +0200 Subject: [PATCH] Do not show install confirm activity if there are no new permissions, externalize app diff for this functionality --- .../org/fdroid/fdroid/installer/AppDiff.java | 69 +++++++++++++++++++ .../installer/InstallConfirmActivity.java | 58 ++++------------ .../fdroid/installer/SystemInstaller.java | 33 +++++++-- 3 files changed, 110 insertions(+), 50 deletions(-) create mode 100644 F-Droid/src/org/fdroid/fdroid/installer/AppDiff.java diff --git a/F-Droid/src/org/fdroid/fdroid/installer/AppDiff.java b/F-Droid/src/org/fdroid/fdroid/installer/AppDiff.java new file mode 100644 index 000000000..c38a7409a --- /dev/null +++ b/F-Droid/src/org/fdroid/fdroid/installer/AppDiff.java @@ -0,0 +1,69 @@ +/* +** +** Copyright 2007, The Android Open Source Project +** Copyright 2015 Dominik Schürmann +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package org.fdroid.fdroid.installer; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.Uri; + +public class AppDiff { + + PackageManager mPm; + PackageInfo mPkgInfo; + + ApplicationInfo mAppInfo = null; + + public AppDiff(PackageManager mPm, Uri mPackageURI) { + this.mPm = mPm; + + final String pkgPath = mPackageURI.getPath(); + + mPkgInfo = mPm.getPackageArchiveInfo(pkgPath, PackageManager.GET_PERMISSIONS); + mPkgInfo.applicationInfo.sourceDir = pkgPath; + mPkgInfo.applicationInfo.publicSourceDir = pkgPath; + + init(); + } + + private void init() { + String pkgName = mPkgInfo.packageName; + // Check if there is already a package on the device with this name + // but it has been renamed to something else. + final String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName }); + if (oldName != null && oldName.length > 0 && oldName[0] != null) { + pkgName = oldName[0]; + mPkgInfo.packageName = pkgName; + mPkgInfo.applicationInfo.packageName = pkgName; + } + // Check if package is already installed. display confirmation dialog if replacing pkg + try { + // This is a little convoluted because we want to get all uninstalled + // apps, but this may include apps with just data, and if it is just + // data we still want to count it as "installed". + mAppInfo = mPm.getApplicationInfo(pkgName, + PackageManager.GET_UNINSTALLED_PACKAGES); + if ((mAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { + mAppInfo = null; + } + } catch (PackageManager.NameNotFoundException e) { + mAppInfo = null; + } + } +} diff --git a/F-Droid/src/org/fdroid/fdroid/installer/InstallConfirmActivity.java b/F-Droid/src/org/fdroid/fdroid/installer/InstallConfirmActivity.java index a60e3e1e9..33b4473f3 100644 --- a/F-Droid/src/org/fdroid/fdroid/installer/InstallConfirmActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/installer/InstallConfirmActivity.java @@ -15,6 +15,7 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ + package org.fdroid.fdroid.installer; import android.app.Activity; @@ -23,9 +24,7 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; @@ -47,9 +46,8 @@ public class InstallConfirmActivity extends Activity implements OnCancelListener private Intent intent; PackageManager mPm; - PackageInfo mPkgInfo; - private ApplicationInfo mAppInfo = null; + AppDiff mAppDiff; // View for install progress View mInstallConfirm; @@ -64,8 +62,8 @@ public class InstallConfirmActivity extends Activity implements OnCancelListener private void startInstallConfirm() { - final Drawable appIcon = mPkgInfo.applicationInfo.loadIcon(mPm); - final String appLabel = (String) mPkgInfo.applicationInfo.loadLabel(mPm); + final Drawable appIcon = mAppDiff.mPkgInfo.applicationInfo.loadIcon(mPm); + final String appLabel = (String) mAppDiff.mPkgInfo.applicationInfo.loadLabel(mPm); View appSnippet = findViewById(R.id.app_snippet); ((ImageView) appSnippet.findViewById(R.id.app_icon)).setImageDrawable(appIcon); @@ -85,12 +83,12 @@ public class InstallConfirmActivity extends Activity implements OnCancelListener mScrollView = null; mOkCanInstall = false; int msg = 0; - if (mPkgInfo != null) { - AppSecurityPermissions perms = new AppSecurityPermissions(this, mPkgInfo); + if (mAppDiff.mPkgInfo != null) { + AppSecurityPermissions perms = new AppSecurityPermissions(this, mAppDiff.mPkgInfo); final int NP = perms.getPermissionCount(AppSecurityPermissions.WHICH_PERSONAL); final int ND = perms.getPermissionCount(AppSecurityPermissions.WHICH_DEVICE); - if (mAppInfo != null) { - msg = (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 + if (mAppDiff.mAppInfo != null) { + msg = (mAppDiff.mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ? R.string.install_confirm_update_system : R.string.install_confirm_update; mScrollView = new CaffeinatedScrollView(this); @@ -139,10 +137,10 @@ public class InstallConfirmActivity extends Activity implements OnCancelListener } } if (!permVisible) { - if (mAppInfo != null) { + if (mAppDiff.mAppInfo != null) { // This is an update to an application, but there are no // permissions at all. - msg = (mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 + msg = (mAppDiff.mAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 ? R.string.install_confirm_update_system_no_perms : R.string.install_confirm_update_no_perms; } else { @@ -178,33 +176,6 @@ public class InstallConfirmActivity extends Activity implements OnCancelListener } } - private void initiateInstall() { - String pkgName = mPkgInfo.packageName; - // Check if there is already a package on the device with this name - // but it has been renamed to something else. - final String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName }); - if (oldName != null && oldName.length > 0 && oldName[0] != null) { - pkgName = oldName[0]; - mPkgInfo.packageName = pkgName; - mPkgInfo.applicationInfo.packageName = pkgName; - } - // Check if package is already installed. display confirmation dialog if replacing pkg - try { - // This is a little convoluted because we want to get all uninstalled - // apps, but this may include apps with just data, and if it is just - // data we still want to count it as "installed". - mAppInfo = mPm.getApplicationInfo(pkgName, - PackageManager.GET_UNINSTALLED_PACKAGES); - if ((mAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { - mAppInfo = null; - } - } catch (NameNotFoundException e) { - mAppInfo = null; - } - - startInstallConfirm(); - } - @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -214,18 +185,15 @@ public class InstallConfirmActivity extends Activity implements OnCancelListener mPm = getPackageManager(); intent = getIntent(); - Uri mPackageURI = intent.getData(); - final String pkgPath = mPackageURI.getPath(); + Uri packageURI = intent.getData(); - mPkgInfo = mPm.getPackageArchiveInfo(pkgPath, PackageManager.GET_PERMISSIONS); - mPkgInfo.applicationInfo.sourceDir = pkgPath; - mPkgInfo.applicationInfo.publicSourceDir = pkgPath; + mAppDiff = new AppDiff(mPm, packageURI); setContentView(R.layout.install_start); mInstallConfirm = findViewById(R.id.install_confirm_panel); mInstallConfirm.setVisibility(View.INVISIBLE); - initiateInstall(); + startInstallConfirm(); } @Override diff --git a/F-Droid/src/org/fdroid/fdroid/installer/SystemInstaller.java b/F-Droid/src/org/fdroid/fdroid/installer/SystemInstaller.java index 925f2e8ee..88d4db2df 100644 --- a/F-Droid/src/org/fdroid/fdroid/installer/SystemInstaller.java +++ b/F-Droid/src/org/fdroid/fdroid/installer/SystemInstaller.java @@ -138,9 +138,32 @@ public class SystemInstaller extends Installer { @Override protected void installPackageInternal(File apkFile) throws AndroidNotCompatibleException { - Intent intent = new Intent(mContext, InstallConfirmActivity.class); - intent.setData(Uri.fromFile(apkFile)); - mActivity.startActivityForResult(intent, REQUEST_CONFIRM_PERMS); + Uri packageUri = Uri.fromFile(apkFile); + if (hasNewPermissions(packageUri)) { + Intent intent = new Intent(mContext, InstallConfirmActivity.class); + intent.setData(packageUri); + mActivity.startActivityForResult(intent, REQUEST_CONFIRM_PERMS); + } else { + try { + doInstallPackageInternal(packageUri); + } catch (AndroidNotCompatibleException e) { + mCallback.onError(InstallerCallback.OPERATION_INSTALL, + InstallerCallback.ERROR_CODE_OTHER); + } + } + } + + private boolean hasNewPermissions(Uri packageUri) { + AppDiff appDiff = new AppDiff(mContext.getPackageManager(), packageUri); + if (appDiff.mPkgInfo != null) { + AppSecurityPermissions perms = new AppSecurityPermissions(mContext, appDiff.mPkgInfo); + if (appDiff.mAppInfo != null) { // it is an update to an existing app + // return false if there are no new permissions + return (perms.getPermissionCount(AppSecurityPermissions.WHICH_NEW) > 0); + } + } + // default: show install confirm activity + return true; } private void doInstallPackageInternal(Uri packageURI) throws AndroidNotCompatibleException { @@ -220,9 +243,9 @@ public class SystemInstaller extends Installer { switch (requestCode) { case REQUEST_CONFIRM_PERMS: if (resultCode == Activity.RESULT_OK) { - final Uri packageURI = data.getData(); + final Uri packageUri = data.getData(); try { - doInstallPackageInternal(packageURI); + doInstallPackageInternal(packageUri); } catch (AndroidNotCompatibleException e) { mCallback.onError(InstallerCallback.OPERATION_INSTALL, InstallerCallback.ERROR_CODE_OTHER);