Merge branch 'last-few-0.100-issues' into 'master'

Last few 0.100 issues

This is a collection of fixes towards issues in 0.100.  It should be also merged into `stable-0.100`.

See merge request !298
This commit is contained in:
Daniel Martí 2016-05-19 10:44:01 +00:00
commit 93ae78b46f
10 changed files with 122 additions and 75 deletions

View File

@ -47,6 +47,7 @@ connected10:
# this file changes every time but should not be cached
- rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
- exit $EXITVALUE
allow_failure: true # remove once install segfaults are gone
connected17:
variables:

View File

@ -139,7 +139,9 @@ public class FDroidApp extends Application {
}
/**
* Initialize the settings needed to run a local swap repo.
* Initialize the settings needed to run a local swap repo. This should
* only ever be called in {@link org.fdroid.fdroid.net.WifiStateChangeService.WifiInfoThread},
* after the single init call in {@link FDroidApp#onCreate()}.
*/
public static void initWifiSettings() {
port = 8888;

View File

@ -57,7 +57,9 @@ public class RepoUpdater {
@NonNull
private final Repo repo;
private boolean hasChanged;
@Nullable
private ProgressListener downloadProgressListener;
private ProgressListener committingProgressListener;
private ProgressListener processXmlProgressListener;
private String cacheTag;
@ -83,6 +85,10 @@ public class RepoUpdater {
this.indexUrl = url;
}
public void setDownloadProgressListener(ProgressListener progressListener) {
this.downloadProgressListener = progressListener;
}
public void setProcessXmlProgressListener(ProgressListener progressListener) {
this.processXmlProgressListener = progressListener;
}
@ -100,6 +106,7 @@ public class RepoUpdater {
try {
downloader = DownloaderFactory.create(context, indexUrl);
downloader.setCacheTag(repo.lastetag);
downloader.setListener(downloadProgressListener);
downloader.download();
if (downloader.isCached()) {

View File

@ -49,8 +49,6 @@ import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.installer.InstallManagerService;
import org.fdroid.fdroid.net.Downloader;
import org.fdroid.fdroid.net.DownloaderService;
import java.net.URL;
import java.util.ArrayList;
@ -166,7 +164,6 @@ public class UpdateService extends IntentService {
public void onDestroy() {
super.onDestroy();
notificationManager.cancel(NOTIFY_ID_UPDATING);
localBroadcastManager.unregisterReceiver(downloadProgressReceiver);
localBroadcastManager.unregisterReceiver(updateStatusReceiver);
}
@ -195,26 +192,6 @@ public class UpdateService extends IntentService {
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private final BroadcastReceiver downloadProgressReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String repoAddress = intent.getDataString();
int downloadedSize = intent.getIntExtra(Downloader.EXTRA_BYTES_READ, -1);
String downloadedSizeFriendly = Utils.getFriendlySize(downloadedSize);
int totalSize = intent.getIntExtra(Downloader.EXTRA_TOTAL_BYTES, -1);
int percent = (int) ((double) downloadedSize / totalSize * 100);
String message;
if (totalSize == -1) {
message = getString(R.string.status_download_unknown_size, repoAddress, downloadedSizeFriendly);
percent = -1;
} else {
String totalSizeFriendly = Utils.getFriendlySize(totalSize);
message = getString(R.string.status_download, repoAddress, downloadedSizeFriendly, totalSizeFriendly, percent);
}
sendStatus(context, STATUS_INFO, message, percent);
}
};
// For receiving results from the UpdateService when we've told it to
// update in response to a user request.
private final BroadcastReceiver updateStatusReceiver = new BroadcastReceiver() {
@ -375,10 +352,7 @@ public class UpdateService extends IntentService {
sendStatus(this, STATUS_INFO, getString(R.string.status_connecting_to_repo, repo.address));
RepoUpdater updater = new RepoUpdater(getBaseContext(), repo);
localBroadcastManager.registerReceiver(downloadProgressReceiver,
DownloaderService.getIntentFilter(updater.indexUrl, Downloader.ACTION_PROGRESS));
updater.setProcessXmlProgressListener(processXmlProgressListener);
updater.setCommittingProgressListener(committingProgressListener);
setProgressListeners(updater);
try {
updater.update();
if (updater.hasChanged()) {
@ -392,7 +366,6 @@ public class UpdateService extends IntentService {
repoErrors.add(e.getMessage());
Log.e(TAG, "Error updating repository " + repo.address, e);
}
localBroadcastManager.unregisterReceiver(downloadProgressReceiver);
// now that downloading the index is done, start downloading updates
if (changes && fdroidPrefs.isAutoDownloadEnabled()) {
@ -528,25 +501,50 @@ public class UpdateService extends IntentService {
notificationManager.notify(NOTIFY_ID_UPDATES_AVAILABLE, builder.build());
}
private final ProgressListener processXmlProgressListener = new ProgressListener() {
@Override
public void onProgress(URL sourceUrl, int bytesRead, int totalBytes) {
String downloadedSize = Utils.getFriendlySize(bytesRead);
String totalSize = Utils.getFriendlySize(totalBytes);
int percent = -1;
if (totalBytes > 0) {
percent = (int) ((double) bytesRead / totalBytes * 100);
/**
* Set up the various {@link ProgressListener}s needed to get feedback to the UI.
* Note: {@code ProgressListener}s do not need to be unregistered, they can just
* be set again for each download.
*/
private void setProgressListeners(RepoUpdater updater) {
updater.setDownloadProgressListener(new ProgressListener() {
@Override
public void onProgress(URL sourceUrl, int bytesRead, int totalBytes) {
Log.i(TAG, "downloadProgressReceiver " + sourceUrl);
String downloadedSizeFriendly = Utils.getFriendlySize(bytesRead);
int percent = (int) ((double) bytesRead / totalBytes * 100);
String message;
if (totalBytes == -1) {
message = getString(R.string.status_download_unknown_size, sourceUrl, downloadedSizeFriendly);
percent = -1;
} else {
String totalSizeFriendly = Utils.getFriendlySize(totalBytes);
message = getString(R.string.status_download, sourceUrl, downloadedSizeFriendly, totalSizeFriendly, percent);
}
sendStatus(getApplicationContext(), STATUS_INFO, message, percent);
}
String message = getString(R.string.status_processing_xml_percent, sourceUrl, downloadedSize, totalSize, percent);
sendStatus(getApplicationContext(), STATUS_INFO, message, percent);
}
};
});
private final ProgressListener committingProgressListener = new ProgressListener() {
@Override
public void onProgress(URL sourceUrl, int bytesRead, int totalBytes) {
String message = getString(R.string.status_inserting_apps);
sendStatus(getApplicationContext(), STATUS_INFO, message);
}
};
updater.setProcessXmlProgressListener(new ProgressListener() {
@Override
public void onProgress(URL sourceUrl, int bytesRead, int totalBytes) {
String downloadedSize = Utils.getFriendlySize(bytesRead);
String totalSize = Utils.getFriendlySize(totalBytes);
int percent = -1;
if (totalBytes > 0) {
percent = (int) ((double) bytesRead / totalBytes * 100);
}
String message = getString(R.string.status_processing_xml_percent, sourceUrl, downloadedSize, totalSize, percent);
sendStatus(getApplicationContext(), STATUS_INFO, message, percent);
}
});
updater.setCommittingProgressListener(new ProgressListener() {
@Override
public void onProgress(URL sourceUrl, int bytesRead, int totalBytes) {
String message = getString(R.string.status_inserting_apps);
sendStatus(getApplicationContext(), STATUS_INFO, message);
}
});
}
}

View File

@ -21,8 +21,12 @@ import java.io.InputStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class App extends ValueObject implements Comparable<App> {
@ -108,12 +112,17 @@ public class App extends ValueObject implements Comparable<App> {
public boolean uninstallable;
public static String getIconName(String packageName, int versionCode) {
return packageName + "_" + versionCode + ".png";
}
@Override
public int compareTo(App app) {
return name.compareToIgnoreCase(app.name);
}
public App() { }
public App() {
}
public App(Cursor cursor) {
@ -273,21 +282,35 @@ public class App extends ValueObject implements Comparable<App> {
+ ", last updated on " + this.lastUpdated + ")</p>";
this.name = (String) appInfo.loadLabel(pm);
this.icon = getIconName(packageName, packageInfo.versionCode);
final SanitizedFile apkFile = SanitizedFile.knownSanitized(appInfo.publicSourceDir);
final Apk apk = new Apk();
apk.versionName = packageInfo.versionName;
apk.versionCode = packageInfo.versionCode;
apk.hashType = "sha256";
apk.hash = Utils.getBinaryHash(apkFile, apk.hashType);
apk.added = this.added;
apk.minSdkVersion = Utils.getMinSdkVersion(context, packageName);
apk.maxSdkVersion = Utils.getMaxSdkVersion(context, packageName);
apk.packageName = this.packageName;
apk.installedFile = apkFile;
apk.permissions = Utils.CommaSeparatedList.make(packageInfo.requestedPermissions);
apk.apkName = apk.packageName + "_" + apk.versionCode + ".apk";
final SanitizedFile apkFile = SanitizedFile.knownSanitized(appInfo.publicSourceDir);
apk.hashType = "sha256";
apk.hash = Utils.getBinaryHash(apkFile, apk.hashType);
apk.installedFile = apkFile;
JarFile jarFile = new JarFile(apkFile);
HashSet<String> abis = new HashSet<>(3);
Pattern pattern = Pattern.compile("^lib/([a-z0-9-]+)/.*");
for (Enumeration<JarEntry> jarEntries = jarFile.entries(); jarEntries.hasMoreElements();) {
JarEntry jarEntry = jarEntries.nextElement();
Matcher matcher = pattern.matcher(jarEntry.getName());
if (matcher.matches()) {
abis.add(matcher.group(1));
}
}
apk.nativecode = Utils.CommaSeparatedList.make(abis.toArray(new String[abis.size()]));
final FeatureInfo[] features = packageInfo.reqFeatures;
if (features != null && features.length > 0) {
final String[] featureNames = new String[features.length];

View File

@ -15,7 +15,7 @@ import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import org.fdroid.fdroid.AppDetails;
import org.fdroid.fdroid.R;
@ -135,12 +135,23 @@ public class InstallManagerService extends Service {
Utils.debugLog(TAG, "onStartCommand " + intent);
if (!ACTION_INSTALL.equals(intent.getAction())) {
Log.i(TAG, "Ignoring " + intent + " as it is not an " + ACTION_INSTALL + " intent");
Utils.debugLog(TAG, "Ignoring " + intent + " as it is not an " + ACTION_INSTALL + " intent");
return START_NOT_STICKY;
}
String urlString = intent.getDataString();
if (TextUtils.isEmpty(urlString)) {
Utils.debugLog(TAG, "empty urlString, nothing to do");
return START_NOT_STICKY;
}
Apk apk = ACTIVE_APKS.get(urlString);
if (apk == null) {
Utils.debugLog(TAG, urlString + " is not in ACTIVE_APKS, why are we trying to download it?");
Toast.makeText(this, urlString + " failed with an imcomplete download request!",
Toast.LENGTH_LONG).show();
return START_NOT_STICKY;
}
Notification notification = createNotification(intent.getDataString(), apk).build();
notificationManager.notify(urlString.hashCode(), notification);

View File

@ -3,7 +3,6 @@ package org.fdroid.fdroid.localrepo;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
@ -237,6 +236,13 @@ public final class LocalRepoManager {
}
}
/**
* Get the {@code index.jar} file that represents the local swap repo.
*/
public File getIndexJar() {
return xmlIndexJar;
}
public void deleteRepo() {
deleteContents(repoDir);
}
@ -267,8 +273,6 @@ public final class LocalRepoManager {
if (!app.isValid()) {
return;
}
PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_META_DATA);
app.icon = getIconFile(packageName, packageInfo.versionCode).getName();
} catch (PackageManager.NameNotFoundException | CertificateEncodingException | IOException e) {
Log.e(TAG, "Error adding app to local repo", e);
return;
@ -277,10 +281,6 @@ public final class LocalRepoManager {
apps.put(packageName, app);
}
public List<String> getApps() {
return new ArrayList<>(apps.keySet());
}
public void copyIconsToRepo() {
ApplicationInfo appInfo;
for (final App app : apps.values()) {
@ -321,7 +321,7 @@ public final class LocalRepoManager {
}
private File getIconFile(String packageName, int versionCode) {
return new File(iconsDir, packageName + "_" + versionCode + ".png");
return new File(iconsDir, App.getIconName(packageName, versionCode));
}
/**
@ -456,6 +456,7 @@ public final class LocalRepoManager {
tag("added", app.installedApk.added);
tagFeatures(app);
tagPermissions(app);
tagNativecode(app);
serializer.endTag("", "package");
}
@ -485,6 +486,14 @@ public final class LocalRepoManager {
serializer.endTag("", "features");
}
private void tagNativecode(App app) throws IOException {
if (app.installedApk.nativecode != null) {
serializer.startTag("", "nativecode");
serializer.text(Utils.CommaSeparatedList.str(app.installedApk.nativecode));
serializer.endTag("", "nativecode");
}
}
private void tagHash(App app) throws IOException {
serializer.startTag("", "hash");
serializer.attribute("", "type", app.installedApk.hashType);

View File

@ -53,7 +53,6 @@ public class WifiStateChangeService extends IntentService {
protected void onHandleIntent(Intent intent) {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_LOWEST);
Utils.debugLog(TAG, "WiFi change service started, clearing info about wifi state until we have figured it out again.");
FDroidApp.initWifiSettings();
NetworkInfo ni = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
int wifiState = wifiManager.getWifiState();
@ -79,6 +78,7 @@ public class WifiStateChangeService extends IntentService {
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_LOWEST);
try {
FDroidApp.initWifiSettings();
Utils.debugLog(TAG, "Checking wifi state (in background thread).");
WifiInfo wifiInfo = null;

View File

@ -245,6 +245,9 @@ public class SwapAppsView extends ListView implements
private final BroadcastReceiver downloadProgressReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (progressView.getVisibility() != View.VISIBLE) {
showProgress();
}
int read = intent.getIntExtra(Downloader.EXTRA_BYTES_READ, 0);
int total = intent.getIntExtra(Downloader.EXTRA_TOTAL_BYTES, 0);
if (total > 0) {

View File

@ -376,7 +376,10 @@ public class SwapWorkflowActivity extends AppCompatActivity {
getService().swapWith(null);
if (!getService().isEnabled()) {
prepareInitialRepo();
if (!LocalRepoManager.get(this).getIndexJar().exists()) {
Utils.debugLog(TAG, "Preparing initial repo with only F-Droid, until we have allowed the user to configure their own repo.");
new PrepareInitialSwapRepo().execute();
}
}
inflateInnerView(R.layout.swap_blank);
@ -452,16 +455,6 @@ public class SwapWorkflowActivity extends AppCompatActivity {
}
}
private void prepareInitialRepo() {
// TODO: Make it so that this and updateSwappableAppsTask (the _real_ swap repo task)
// don't stomp on eachothers toes. The other one should wait for this to finish, or cancel
// this, but this should never take precedence over the other.
// TODO: Also don't allow this to run multiple times (e.g. if a user keeps navigating back
// to the main screen.
Utils.debugLog(TAG, "Preparing initial repo with only F-Droid, until we have allowed the user to configure their own repo.");
new PrepareInitialSwapRepo().execute();
}
/**
* Once the UpdateAsyncTask has finished preparing our repository index, we can
* show the next screen to the user. This will be one of two things: