3572 Commits

Author SHA1 Message Date
Hans-Christoph Steiner
f949c5807f make swap install via InstallManagerService
Somehow, it ended up that there was a partial reimplementation of the
install in SwapWorkflowActivity.
2016-06-01 22:29:36 +02:00
Hans-Christoph Steiner
9d2fe4000d use download URL as unique ID through the whole install process
InstallManagerService and DownloaderService both use the download URL as
the unique ID to represent a given APK install through the whole lifecycle
of the install and download process.  This converts the installer stuff to
use the same semantics.  A Uri instance is mostly used there because its
the most useful format, but ultimately, the String, Uri, and int all derive
from the exact same URL.  This then removes the local APK URI from use in
the installer broadcasts.

While I normally think reusing terms from Android is the best thing to do,
"originating URI" drives me nuts because it is almost nonsense English.
"Originating" is a verb in the continuous form, meaning that it is an
action that is ongoing.  A URI is a static thing, and in this case, a URI
that points to a file that is completely downloaded.  I left the term in
place for DefaultInstaller because it wraps PackageManager, which is where
that term originates.

This handles "Use strings instead of Uris in InstallManagerService for
urlString" as listed in #680
2016-06-01 22:29:36 +02:00
Hans-Christoph Steiner
9c1b917604 Merge branch 'installerservice-wip' into 'master'
InstallerService

This merge request mainly introduces the ``InstallerService``. Many files have been touched and reworked in this merge request, due to the following changes:
* After download of an apk in ``InstallManagerService``, the ``InstallerService``is started an kicks off the installation process. For unattended installers this directly runs through without any user interaction, for the default installer a new PendingIntent containing ``DefaultActivityInstaller`` is returned that is either stuffed into the notification or directly started from ``AppDetails``
* Using local broadcasts, ``InstallManagerService`` and ``AppDetails`` are informed of state changes in the installation process
* ``DefaultActivityInstaller`` is a wrapper around the default installation APIs of Android
* If the unattended ``PrivilegedInstaller`` is available, a permission screen is shown before download
* Actual error codes and messages are displayed in notification or dialog on fail, especially interesting when using the ``PrivilegedInstaller``
* The process for installing the Privileged Extension has been moved into an own installer for logic seperation, called ``ExtensionInstaller``

Some design considerations:
* I try to use Uris where ever possible. At some points this clashes with the usage of ``urlString`` in ``InstallManagerService``. This could be fixed in a later merge request

Some other TODOs are left, but I would like to do them after this merge request has been merged if it's okay, as this one is already too huge:
* Check if apk permissions are the same as announced in the permission screen for ``PrivilegedInstaller``
* In ``Installer.newPermissionCount()``, I need the target SDK before download to check if it's targetting Android M, which does not require the permission screen
* Introduce FileProvider for Android N
* Redesign layout of ``InstallConfirmActivity``
* Remove "cancel" icon for installing progress in AppDetails

See merge request !300
2016-06-01 15:06:38 +00:00
Dominik Schürmann
b149cd64fd Removes remaining scopes from switch statements 2016-06-01 14:12:59 +02:00
Dominik Schürmann
619c4f284b Fix crash for apks with no permissions 2016-06-01 02:14:54 +02:00
Dominik Schürmann
1aa87ddf76 PrivilegedInstaller: Fix check for granted permissions
The onConnected callback of ServiceConnection is always
executed on the main looper of the context that is used
to create the service binding. Thus the old code resulted
in a deadlock and then in a timeout of the Thread.wait()
method.

The check for permissions is now called inside install and
uninstall callbacks, where it works asynchronously.
2016-06-01 02:14:51 +02:00
Dominik Schürmann
0b92806327 New error dialog on failed installs 2016-05-31 22:44:58 +02:00
Dominik Schürmann
5f1b7488f0 More Log.e for isExtensionInstalledCorrectly 2016-05-31 17:52:45 +02:00
Dominik Schürmann
886c67e452 Fix NPE for uninstall of extension 2016-05-31 17:28:55 +02:00
Dominik Schürmann
c5ae43d66c Remove UI code from PrivilegedInstaller 2016-05-31 17:15:07 +02:00
Dominik Schürmann
9e0787f23d Add javadoc to installer classes 2016-05-31 17:15:07 +02:00
Dominik Schürmann
b994b1c895 Fix selection of ExtensionInstaller 2016-05-31 17:15:07 +02:00
Dominik Schürmann
13f2e30a40 Make InstallerService an IntentService
Because only one apk should be installed at a time
and no cancelation is required it is sufficient to
use an IntentService
2016-05-31 17:15:07 +02:00
Dominik Schürmann
d6803e1bf4 Remove scopes from switch statements
also change two-case switch statements to if-else
2016-05-31 17:15:07 +02:00
Dominik Schürmann
f860257826 Fix pmd errors and code style 2016-05-31 17:15:07 +02:00
Dominik Schürmann
d3a7107a0f Fix checkstyle errors 2016-05-31 17:15:07 +02:00
Dominik Schürmann
2776b86050 Redesign PrivilegedInstaller
* use new local broadcasts
* show permission screen before download
* display permission screen as dialog
2016-05-31 17:15:07 +02:00
Dominik Schürmann
592cd0424a Better error handling for priv installer 2016-05-31 17:14:31 +02:00
Dominik Schürmann
4e8e148029 Display install errors as notify/dialog 2016-05-31 17:14:31 +02:00
Dominik Schürmann
de1d310499 Move installation of extension into own Installer 2016-05-31 17:14:31 +02:00
Dominik Schürmann
c5f9070370 Better error handling in privileged installer 2016-05-31 17:14:31 +02:00
Dominik Schürmann
bb273cd2f5 Use Uris more often instead of File 2016-05-31 17:14:31 +02:00
Dominik Schürmann
a2356b05d6 Refactor installer package 2016-05-31 17:13:53 +02:00
Dominik Schürmann
6d2f2d20a8 InstallerService 2016-05-31 17:13:26 +02:00
Hans-Christoph Steiner
4ef0642134 Merge branch 'ci-bumps' into 'master'
PMD and Checkstyle version bumps



See merge request !316
2016-05-31 14:39:04 +00:00
Daniel Martí
08e067c6ba pmd: bump to 5.4.2
This is a bugfix release where they mostly fixed false positives. No
changes required.
2016-05-30 22:08:19 +01:00
Daniel Martí
d4bb97db72 checkstyle: bump to 6.19
Seems like they finally fixed the hanging throws indent issue.
2016-05-30 22:04:33 +01:00
Daniel Martí
5e2da57565 Merge branch 'bump-minsdk' into 'master'
Bump minSdkVersion to 10, remove all compat code

Summary of changes:

* Remove compat apply()
* Remove compat setReadable()
* Remove pre-10 compat code in swap
* Remove pre-10 compat code in PRNGFixes

Fixes #663.

See merge request !296
2016-05-30 18:40:38 +00:00
Daniel Martí
cd1c213fb2 Bump minSdkVersion to 10, remove all compat code
Summary of changes:

* Remove compat apply()
* Remove compat setReadable()
* Remove pre-10 compat code in swap
* Remove pre-10 compat code in PRNGFixes

Fixes #663.
2016-05-30 19:25:06 +01:00
Daniel Martí
1bfd3425c9 Merge branch 'prep-for-InstalledAppProviderService' into 'master'
Prep for InstalledAppProviderService

This is basically a collection of little fixes in preparations for !299 .

See merge request !313
2016-05-27 20:31:00 +00:00
Hans-Christoph Steiner
a03629d29d SanitizedFileTest requires systems with "/" for a path separator
closes #622 https://gitlab.com/fdroid/fdroidclient/issues/622
2016-05-27 22:00:28 +02:00
Hans-Christoph Steiner
1914f5f3e1 remove unused app.uninstallable
app.uninstallable is only used in AppDetails.  It is only set when
generating App instances from installed APKs for the swap stuff. Since it
is initialized to false and used as !app.uninstallable, it is always true
when used.  So it was doing nothing.

This needs to be thought out more so this is not entirely complete for
#628. AppDetails needs to know whether its a system app to provide proper
feedback and swap needs to know whether its a system app with an update
installed, otherwise it should ignore it.
2016-05-27 22:00:28 +02:00
Hans-Christoph Steiner
f7688d7f9a convert App comments to javadoc so they can be read in popups, etc.
Decent Java editors have all sorts of nice ways to show javadoc comments,
whether they are for public or private APIs.  So comments should be in that
format whenever possible.
2016-05-27 22:00:28 +02:00
Hans-Christoph Steiner
1410a720c8 reorganize swap's App() constructor to prepare for database caching
To generate swap's index.jar, lots of information about all the installed
APKs needs to be parsed.  That can take a long time.  Some of that can be
stored in InstalledAppProvider.  This prepares for those changes.

Also, turns out that packageInfo.applicationInfo provides enough info, so
there is no need to use pm.getApplicationInfo().  And the metadata from
GET_META_DATA was not even being used.
2016-05-27 22:00:28 +02:00
Hans-Christoph Steiner
aca94bcb68 move Provider tests into same java package the Providers
This allows the tests to call more methods directly without having to use
`public` visibility.
2016-05-27 22:00:28 +02:00
Hans-Christoph Steiner
c947f24495 simple test for WifiStateChangeService.formatIpAddress()
94f79a6438c7021db9c02003865c17f3a0da1718 made me want to be sure
2016-05-27 16:15:15 +02:00
Hans-Christoph Steiner
68375163f5 only use swap header image on large screens
The previous logic was putting the header on some 4" screens while not
putting it on a 7" tablet.  Tested with:

* Samsung Galaxy Tab 3 7"
* Azpen A727 7"
* Xiaomi 4.5"
* Lenovo 4"
* emulators...
2016-05-27 16:15:15 +02:00
Hans-Christoph Steiner
1591851273 remove "Try to install" from swap UI
This should no longer be necessary since the local swap repo metadata now
includes the nativecode tag.

#30 https://gitlab.com/fdroid/fdroidclient/issues/30
2016-05-27 16:15:15 +02:00
Hans-Christoph Steiner
15005372a2 mark as compatible when App/Apk instances are from installed apps
By definition, an app that is already installed is compatible.
2016-05-27 12:26:17 +02:00
Daniel Martí
77376dfa42 Merge branch 'fix-empty-app-list' into 'master'
Use initLoader instead of resetartLoader. Call onResume after setting category.

While working on !311, I had some logging in place in the `AppProvider`. I ended up straying into an investigation of issue #606 and noticed with my logging that we have been doing more queries than required for some time, because the loader was being forceably recreated when it could instead be reused in onResume.

Perhaps more importantly, we were querying twice for list of apps to display. The first time is "Give me all the apps" because we haven't set the category yet. Then we set the category, which causes us to ask for "Apps matching this category". The fix for this is for the `onResume` method (which results in a cursor being created) to be called _after_ setting the selected category is set. This ensures that the query is run has the correct category the first time, and needn't be run again.

I am not confident that this fixes the issue in #606, but I haven't seen it reproduced since I've implemented this fix.

See merge request !312
2016-05-26 13:12:25 +00:00
Peter Serwylo
810e8eae0d Use initLoader instead of resetartLoader. Call onResume after setting category.
While investigating the infamous issue #606, I noticed these two things which
were a little off. Firstly, we were doing more queries than required, because the
loader was being forceably recreated when it could instead be reused in onResume.

Also, the onResume method (which results in a cursor beign created) should be
called _after_ setting the selected category. This ensures that the query
which is run has the correct category the first time, and needn't be run again.

I am not confident that this fixes the issue, but it seems to help, and I believe
it is the correct thing to do even if it doesn't fix 606.
2016-05-26 10:58:17 +10:00
Hans-Christoph Steiner
082a2f5fef Merge branch '0.100-alpha8-fixes' into 'master'
0.100 alpha8 fixes

3 bug fixes for ACRA crash reports

See merge request !310
2016-05-25 00:31:45 +00:00
Hans-Christoph Steiner
94f79a6438 prevent crash caused by bad netmask given to WifiStateChangeService
My guess is that is from IPv6, but those should be filtered out in this
code before it gets to the crash point.  Here's the stacktrace:

java.lang.RuntimeException: An error occured while executing doInBackground()
	at android.os.AsyncTask$3.done(AsyncTask.java:300)
	at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
	at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
	at java.util.concurrent.FutureTask.run(FutureTask.java:242)
	at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
	at java.lang.Thread.run(Thread.java:841)
Caused by: java.lang.IllegalArgumentException: Value [64] not in range [0,32]
	at org.apache.commons.net.util.SubnetUtils.rangeCheck(SubnetUtils.java:339)
	at org.apache.commons.net.util.SubnetUtils.calculate(SubnetUtils.java:264)
	at org.apache.commons.net.util.SubnetUtils.<init>(SubnetUtils.java:51)
	at org.fdroid.fdroid.net.WifiStateChangeService.setIpInfoFromNetworkInterface(WifiStateChangeService.java:222)
	at org.fdroid.fdroid.net.WifiStateChangeService.access$300(WifiStateChangeService.java:37)
	at org.fdroid.fdroid.net.WifiStateChangeService$WaitForWifiAsyncTask.doInBackground(WifiStateChangeService.java:99)
	at org.fdroid.fdroid.net.WifiStateChangeService$WaitForWifiAsyncTask.doInBackground(WifiStateChangeService.java:71)
	at android.os.AsyncTask$2.call(AsyncTask.java:288)
	at java.util.concurrent.FutureTask.run(FutureTask.java:237)
	... 4 more
java.lang.IllegalArgumentException: Value [64] not in range [0,32]
	at org.apache.commons.net.util.SubnetUtils.rangeCheck(SubnetUtils.java:339)
	at org.apache.commons.net.util.SubnetUtils.calculate(SubnetUtils.java:264)
	at org.apache.commons.net.util.SubnetUtils.<init>(SubnetUtils.java:51)
	at org.fdroid.fdroid.net.WifiStateChangeService.setIpInfoFromNetworkInterface(WifiStateChangeService.java:222)
	at org.fdroid.fdroid.net.WifiStateChangeService.access$300(WifiStateChangeService.java:37)
	at org.fdroid.fdroid.net.WifiStateChangeService$WaitForWifiAsyncTask.doInBackground(WifiStateChangeService.java:99)
	at org.fdroid.fdroid.net.WifiStateChangeService$WaitForWifiAsyncTask.doInBackground(WifiStateChangeService.java:71)
	at android.os.AsyncTask$2.call(AsyncTask.java:288)
	at java.util.concurrent.FutureTask.run(FutureTask.java:237)
	at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
	at java.lang.Thread.run(Thread.java:841)
2016-05-24 21:47:45 +02:00
Hans-Christoph Steiner
2897dcb67e fix crash when InstallManager is killed while actively downloading
This is very related to #660 but this time, I can't see any other way to
solve it but a null guard.  I don't think it is possible to guarantee that
the Downloader.ACTION_INTERRUPTED receiver will be unregistered since
onDestroy() might not even be called.

java.lang.NullPointerException
	at org.fdroid.fdroid.installer.InstallManagerService.removeFromActive(InstallManagerService.java:328)
	at org.fdroid.fdroid.installer.InstallManagerService.access$400(InstallManagerService.java:58)
	at org.fdroid.fdroid.installer.InstallManagerService$4.onReceive(InstallManagerService.java:212)
	at android.support.v4.content.LocalBroadcastManager.executePendingBroadcasts(LocalBroadcastManager.java:297)
	at android.support.v4.content.LocalBroadcastManager.access$000(LocalBroadcastManager.java:46)
	at android.support.v4.content.LocalBroadcastManager$1.handleMessage(LocalBroadcastManager.java:116)
	at android.os.Handler.dispatchMessage(Handler.java:110)
	at android.os.Looper.loop(Looper.java:193)
	at android.app.ActivityThread.main(ActivityThread.java:5353)
	at java.lang.reflect.Method.invokeNative(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:515)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:830)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:646)
	at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
	at dalvik.system.NativeStart.main(Native Method)
2016-05-24 21:47:45 +02:00
Hans-Christoph Steiner
fb3dcb293d fix crash with Bluetooth on android-10
android.bluetooth.BluetoothSocket.isConnected() is only 14+

java.lang.NoSuchMethodError: android.bluetooth.BluetoothSocket.isConnected
  at org.fdroid.fdroid.net.bluetooth.BluetoothConnection.open(BluetoothConnection.java:37)
  at org.fdroid.fdroid.net.bluetooth.BluetoothClient.openConnection(BluetoothClient.java:31)
  at org.fdroid.fdroid.net.BluetoothDownloader.<init>(BluetoothDownloader.java:30)
  at org.fdroid.fdroid.net.DownloaderFactory.create(DownloaderFactory.java:56)
  at org.fdroid.fdroid.RepoUpdater.downloadIndex(RepoUpdater.java:97)
  at org.fdroid.fdroid.RepoUpdater.update(RepoUpdater.java:131)
  at org.fdroid.fdroid.UpdateService.onHandleIntent(UpdateService.java:377)
  at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loop(Looper.java:130)
  at android.os.HandlerThread.run(HandlerThread.java:60)
2016-05-24 21:47:45 +02:00
Daniel Martí
3f525c9bae Merge branch 'parsing-and-notifications' into 'master'
parsing and notification fixes

This is a follow up to !306

See merge request !309
2016-05-24 15:35:26 +00:00
Hans-Christoph Steiner
5f623e0c4a after downloading is complete, update notification to "Tap to install"
f9a30d2e1c9d95302e8f4dd0e733d019f70bed66 broke the "Tap to install" aspect.
2016-05-24 09:25:11 +02:00
Hans-Christoph Steiner
f08f8cb53d only parse <uses-sdk> once when looking for min/max SDK version
When building APK instances from installed apps, the minSdkVersion and
maxSdkVersion needs to be parsed directly from the APK's Android Manifest,
since PackageManager does not provide a method to get it how we need it.
Previously, the whole AndroidManifest.xml file was parsed entirely twice,
once for minSdkVersion then for maxSdkVersion.
2016-05-24 09:25:11 +02:00
Hans-Christoph Steiner
02d98826a9 when parsing APKs for the local repo, correctly set maxSdkVersion
The original logic had maxSdkVersion=0 meaning infinity. That was changed
to be a very large value SDK_VERSION_MAX_VALUE, but getMinMaxSdkVersion()
was still returning 0 for APKs where maxSdkVersion was not set.

This is a follow up on fc0df0dcf4dd0d5f13de82d7cd9254b2b48cb62d
2016-05-24 09:25:11 +02:00
Hans-Christoph Steiner
d54748ff39 SuppressLint("ParcelCreator") on MockApplicationInfo
Apparently, the CREATOR field is not (yet?) needed in the tests, since
they work without it.  This gets us closer to making lint errors fail
the CI builds.

closes #580
2016-05-24 09:24:25 +02:00