Merge branch 'more-fixes' into 'master'

A few Java fixes and tweaks, enable more PMD rules



See merge request !266
This commit is contained in:
Peter Serwylo 2016-04-25 12:19:46 +00:00
commit 7a880fdc33
27 changed files with 288 additions and 251 deletions

View File

@ -58,6 +58,8 @@ To get all the logcat messages by F-Droid, you can run:
* Use gradle with `--daemon` if you are going to build F-Droid multiple times. * Use gradle with `--daemon` if you are going to build F-Droid multiple times.
* If you get a message like `Could not find com.android.support:support-...`, * If you get a message like `Could not find com.android.support:support-...`,
make sure that you have the latest Android support maven repository. make sure that you have the latest Android support maven repository.
* When building as part of AOSP with `Android.mk`, make sure you have a
recent version of Gradle installed as `gradlew` will not be used.
## Running the test suite ## Running the test suite

View File

@ -208,16 +208,8 @@ pmd {
} }
task pmd(type: Pmd, dependsOn: assembleDebug) { task pmd(type: Pmd, dependsOn: assembleDebug) {
ruleSets = [ ruleSetFiles = files("${project.rootDir}/config/pmd/rules.xml")
//'java-basic', ruleSets = [] // otherwise defaults clash with the list in rules.xml
'java-unusedcode',
'java-android',
'java-clone',
'java-finalizers',
'java-imports',
'java-migrating',
//'java-unnecessary', // too nitpicky with parenthesis
]
source 'src/main/java', 'src/test/java', 'src/androidTest/java' source 'src/main/java', 'src/test/java', 'src/androidTest/java'
include '**/*.java' include '**/*.java'
} }

View File

@ -7,7 +7,7 @@ import org.fdroid.fdroid.R;
public class MockFDroidResources extends MockResources { public class MockFDroidResources extends MockResources {
private Context getStringDelegatingContext; private final Context getStringDelegatingContext;
public MockFDroidResources(Context getStringDelegatingContext) { public MockFDroidResources(Context getStringDelegatingContext) {
this.getStringDelegatingContext = getStringDelegatingContext; this.getStringDelegatingContext = getStringDelegatingContext;

View File

@ -10,7 +10,7 @@ import java.util.List;
public class MockInstallablePackageManager extends MockPackageManager { public class MockInstallablePackageManager extends MockPackageManager {
private List<PackageInfo> info = new ArrayList<>(); private final List<PackageInfo> info = new ArrayList<>();
@Override @Override
public List<PackageInfo> getInstalledPackages(int flags) { public List<PackageInfo> getInstalledPackages(int flags) {

View File

@ -30,14 +30,13 @@ public class FileCompatTest {
private static final String TAG = "FileCompatTest"; private static final String TAG = "FileCompatTest";
private File dir;
private SanitizedFile sourceFile; private SanitizedFile sourceFile;
private SanitizedFile destFile; private SanitizedFile destFile;
@Before @Before
public void setUp() { public void setUp() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
dir = TestUtils.getWriteableDir(instrumentation); File dir = TestUtils.getWriteableDir(instrumentation);
sourceFile = SanitizedFile.knownSanitized(TestUtils.copyAssetToDir(instrumentation.getContext(), "simpleIndex.jar", dir)); sourceFile = SanitizedFile.knownSanitized(TestUtils.copyAssetToDir(instrumentation.getContext(), "simpleIndex.jar", dir));
destFile = new SanitizedFile(dir, "dest-" + UUID.randomUUID() + ".testproduct"); destFile = new SanitizedFile(dir, "dest-" + UUID.randomUUID() + ".testproduct");
assertFalse(destFile.exists()); assertFalse(destFile.exists());

View File

@ -160,7 +160,7 @@ public class MultiRepoUpdaterTest extends InstrumentationTestCase {
* repository indeed contains the apks that it said it would provide. * repository indeed contains the apks that it said it would provide.
*/ */
private void assertExpected() { private void assertExpected() {
Log.d(TAG, "Asserting all versions of each .apk are in index."); Log.i(TAG, "Asserting all versions of each .apk are in index.");
List<Repo> repos = RepoProvider.Helper.all(context); List<Repo> repos = RepoProvider.Helper.all(context);
assertEquals("Repos", 3, repos.size()); assertEquals("Repos", 3, repos.size());
@ -173,7 +173,7 @@ public class MultiRepoUpdaterTest extends InstrumentationTestCase {
* *
*/ */
private void assertSomewhatAcceptable() { private void assertSomewhatAcceptable() {
Log.d(TAG, "Asserting at least one versions of each .apk is in index."); Log.i(TAG, "Asserting at least one versions of each .apk is in index.");
List<Repo> repos = RepoProvider.Helper.all(context); List<Repo> repos = RepoProvider.Helper.all(context);
assertEquals("Repos", 3, repos.size()); assertEquals("Repos", 3, repos.size());

View File

@ -200,7 +200,7 @@ public class TestUtils {
OutputStream output = null; OutputStream output = null;
try { try {
tempFile = File.createTempFile(assetName + "-", ".testasset", directory); tempFile = File.createTempFile(assetName + "-", ".testasset", directory);
Log.d(TAG, "Copying asset file " + assetName + " to directory " + directory); Log.i(TAG, "Copying asset file " + assetName + " to directory " + directory);
input = context.getAssets().open(assetName); input = context.getAssets().open(assetName);
output = new FileOutputStream(tempFile); output = new FileOutputStream(tempFile);
Utils.copy(input, output); Utils.copy(input, output);

View File

@ -37,7 +37,7 @@ public final class QRCodeEncoder {
private static final int WHITE = 0xFFFFFFFF; private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000; private static final int BLACK = 0xFF000000;
private int dimension = Integer.MIN_VALUE; private final int dimension;
private String contents; private String contents;
private String displayContents; private String displayContents;
private String title; private String title;

View File

@ -68,7 +68,7 @@ import java.util.zip.ZipFile;
* @see <a href="https://stackoverflow.com/a/4761689">a binary XML parser</a> * @see <a href="https://stackoverflow.com/a/4761689">a binary XML parser</a>
*/ */
public class AndroidXMLDecompress { public class AndroidXMLDecompress {
public static int startTag = 0x00100102; public static final int START_TAG = 0x00100102;
/** /**
* Just get the XML attributes from the {@code <manifest>} element. * Just get the XML attributes from the {@code <manifest>} element.
@ -82,7 +82,7 @@ public class AndroidXMLDecompress {
int stringTableOffset = stringIndexTableOffset + numbStrings * 4; int stringTableOffset = stringIndexTableOffset + numbStrings * 4;
int xmlTagOffset = littleEndianWord(binaryXml, 3 * 4); int xmlTagOffset = littleEndianWord(binaryXml, 3 * 4);
for (int i = xmlTagOffset; i < binaryXml.length - 4; i += 4) { for (int i = xmlTagOffset; i < binaryXml.length - 4; i += 4) {
if (littleEndianWord(binaryXml, i) == startTag) { if (littleEndianWord(binaryXml, i) == START_TAG) {
xmlTagOffset = i; xmlTagOffset = i;
break; break;
} }
@ -92,11 +92,11 @@ public class AndroidXMLDecompress {
while (offset < binaryXml.length) { while (offset < binaryXml.length) {
int tag0 = littleEndianWord(binaryXml, offset); int tag0 = littleEndianWord(binaryXml, offset);
if (tag0 == startTag) { if (tag0 == START_TAG) {
int numbAttrs = littleEndianWord(binaryXml, offset + 7 * 4); int numbAttrs = littleEndianWord(binaryXml, offset + 7 * 4);
offset += 9 * 4; offset += 9 * 4;
HashMap<String, Object> attributes = new HashMap<String, Object>(3); HashMap<String, Object> attributes = new HashMap<>(3);
for (int i = 0; i < numbAttrs; i++) { for (int i = 0; i < numbAttrs; i++) {
int attributeNameStringIndex = littleEndianWord(binaryXml, offset + 1 * 4); int attributeNameStringIndex = littleEndianWord(binaryXml, offset + 1 * 4);
int attributeValueStringIndex = littleEndianWord(binaryXml, offset + 2 * 4); int attributeValueStringIndex = littleEndianWord(binaryXml, offset + 2 * 4);
@ -117,7 +117,7 @@ public class AndroidXMLDecompress {
// we only need the first <manifest> start tag // we only need the first <manifest> start tag
break; break;
} }
return new HashMap<String, Object>(0); return new HashMap<>(0);
} }
public static byte[] getManifestFromFilename(String filename) throws IOException { public static byte[] getManifestFromFilename(String filename) throws IOException {
@ -137,9 +137,7 @@ public class AndroidXMLDecompress {
is.read(buf); is.read(buf);
is.close(); is.close();
if (zip != null) {
zip.close(); zip.close();
}
return buf; return buf;
} }

View File

@ -439,7 +439,9 @@ public class AppDetails extends AppCompatActivity {
*/ */
private void cleanUpFinishedDownload() { private void cleanUpFinishedDownload() {
activeDownloadUrlString = null; activeDownloadUrlString = null;
if (headerFragment != null) {
headerFragment.removeProgress(); headerFragment.removeProgress();
}
unregisterDownloaderReceivers(); unregisterDownloaderReceivers();
} }
@ -464,6 +466,9 @@ public class AppDetails extends AppCompatActivity {
} }
private void unregisterDownloaderReceivers() { private void unregisterDownloaderReceivers() {
if (localBroadcastManager == null) {
return;
}
localBroadcastManager.unregisterReceiver(startedReceiver); localBroadcastManager.unregisterReceiver(startedReceiver);
localBroadcastManager.unregisterReceiver(progressReceiver); localBroadcastManager.unregisterReceiver(progressReceiver);
localBroadcastManager.unregisterReceiver(completeReceiver); localBroadcastManager.unregisterReceiver(completeReceiver);
@ -863,8 +868,7 @@ public class AppDetails extends AppCompatActivity {
} }
private void startDownload(Apk apk, String repoAddress) { private void startDownload(Apk apk, String repoAddress) {
String urlString = Utils.getApkUrl(repoAddress, apk); activeDownloadUrlString = Utils.getApkUrl(repoAddress, apk);
activeDownloadUrlString = urlString;
registerDownloaderReceivers(); registerDownloaderReceivers();
headerFragment.startProgress(); headerFragment.startProgress();
DownloaderService.queue(this, apk.packageName, activeDownloadUrlString); DownloaderService.queue(this, apk.packageName, activeDownloadUrlString);

View File

@ -268,7 +268,7 @@ public class RepoXMLHandler extends DefaultHandler {
curchars.setLength(0); curchars.setLength(0);
} }
private String cleanWhiteSpace(@Nullable String str) { private static String cleanWhiteSpace(@Nullable String str) {
return str == null ? null : str.replaceAll("\\s", " "); return str == null ? null : str.replaceAll("\\s", " ");
} }
} }

View File

@ -489,6 +489,7 @@ public class UpdateService extends IntentService implements ProgressListener {
AppProvider.DataColumns.PACKAGE_NAME, AppProvider.DataColumns.PACKAGE_NAME,
AppProvider.DataColumns.SUGGESTED_VERSION_CODE, AppProvider.DataColumns.SUGGESTED_VERSION_CODE,
}, null, null, null); }, null, null, null);
if (cursor != null) {
cursor.moveToFirst(); cursor.moveToFirst();
for (int i = 0; i < cursor.getCount(); i++) { for (int i = 0; i < cursor.getCount(); i++) {
App app = new App(cursor); App app = new App(cursor);
@ -499,6 +500,8 @@ public class UpdateService extends IntentService implements ProgressListener {
DownloaderService.queue(this, app.packageName, urlString); DownloaderService.queue(this, app.packageName, urlString);
cursor.moveToNext(); cursor.moveToNext();
} }
cursor.close();
}
} }
private void showAppUpdatesNotification(Cursor hasUpdates) { private void showAppUpdatesNotification(Cursor hasUpdates) {

View File

@ -572,7 +572,7 @@ public class AppProvider extends FDroidProvider {
public static Uri getSearchUri(Repo repo, String query) { public static Uri getSearchUri(Repo repo, String query) {
return getContentUri().buildUpon() return getContentUri().buildUpon()
.appendPath(PATH_SEARCH_REPO) .appendPath(PATH_SEARCH_REPO)
.appendPath(repo.id + "") .appendPath(String.valueOf(repo.id))
.appendPath(query) .appendPath(query)
.build(); .build();
} }

View File

@ -116,7 +116,9 @@ class DBHelper extends SQLiteOpenHelper {
} }
private void populateRepoNames(SQLiteDatabase db, int oldVersion) { private void populateRepoNames(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 37) { if (oldVersion >= 37) {
return;
}
Utils.debugLog(TAG, "Populating repo names from the url"); Utils.debugLog(TAG, "Populating repo names from the url");
final String[] columns = {"address", "_id"}; final String[] columns = {"address", "_id"};
Cursor cursor = db.query(TABLE_REPO, columns, Cursor cursor = db.query(TABLE_REPO, columns,
@ -139,10 +141,11 @@ class DBHelper extends SQLiteOpenHelper {
cursor.close(); cursor.close();
} }
} }
}
private void renameRepoId(SQLiteDatabase db, int oldVersion) { private void renameRepoId(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 36 && !columnExists(db, TABLE_REPO, "_id")) { if (oldVersion >= 36 || columnExists(db, TABLE_REPO, "_id")) {
return;
}
Utils.debugLog(TAG, "Renaming " + TABLE_REPO + ".id to _id"); Utils.debugLog(TAG, "Renaming " + TABLE_REPO + ".id to _id");
db.beginTransaction(); db.beginTransaction();
@ -190,7 +193,6 @@ class DBHelper extends SQLiteOpenHelper {
} }
db.endTransaction(); db.endTransaction();
} }
}
@Override @Override
public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) {
@ -299,7 +301,9 @@ class DBHelper extends SQLiteOpenHelper {
* key in sqlite - table must be recreated). * key in sqlite - table must be recreated).
*/ */
private void migrateRepoTable(SQLiteDatabase db, int oldVersion) { private void migrateRepoTable(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 20) { if (oldVersion >= 20) {
return;
}
List<Repo> oldrepos = new ArrayList<>(); List<Repo> oldrepos = new ArrayList<>();
Cursor cursor = db.query(TABLE_REPO, Cursor cursor = db.query(TABLE_REPO,
new String[] {"address", "inuse", "pubkey"}, new String[] {"address", "inuse", "pubkey"},
@ -330,7 +334,6 @@ class DBHelper extends SQLiteOpenHelper {
db.insert(TABLE_REPO, null, values); db.insert(TABLE_REPO, null, values);
} }
} }
}
private void insertNameAndDescription(SQLiteDatabase db, private void insertNameAndDescription(SQLiteDatabase db,
int addressResId, int nameResId, int descriptionResId) { int addressResId, int nameResId, int descriptionResId) {
@ -350,7 +353,9 @@ class DBHelper extends SQLiteOpenHelper {
private void addNameAndDescriptionToRepo(SQLiteDatabase db, int oldVersion) { private void addNameAndDescriptionToRepo(SQLiteDatabase db, int oldVersion) {
boolean nameExists = columnExists(db, TABLE_REPO, "name"); boolean nameExists = columnExists(db, TABLE_REPO, "name");
boolean descriptionExists = columnExists(db, TABLE_REPO, "description"); boolean descriptionExists = columnExists(db, TABLE_REPO, "description");
if (oldVersion < 21 && !(nameExists && descriptionExists)) { if (oldVersion >= 21 || (nameExists && descriptionExists)) {
return;
}
if (!nameExists) { if (!nameExists) {
db.execSQL("alter table " + TABLE_REPO + " add column name text"); db.execSQL("alter table " + TABLE_REPO + " add column name text");
} }
@ -365,7 +370,6 @@ class DBHelper extends SQLiteOpenHelper {
R.string.guardianproject_repo_name, R.string.guardianproject_repo_description); R.string.guardianproject_repo_name, R.string.guardianproject_repo_description);
insertNameAndDescription(db, R.string.guardianproject_archive_address, insertNameAndDescription(db, R.string.guardianproject_archive_address,
R.string.guardianproject_archive_name, R.string.guardianproject_archive_description); R.string.guardianproject_archive_name, R.string.guardianproject_archive_description);
}
} }
@ -374,7 +378,9 @@ class DBHelper extends SQLiteOpenHelper {
* calculate its fingerprint and save it to the database. * calculate its fingerprint and save it to the database.
*/ */
private void addFingerprintToRepo(SQLiteDatabase db, int oldVersion) { private void addFingerprintToRepo(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 44) { if (oldVersion >= 44) {
return;
}
if (!columnExists(db, TABLE_REPO, "fingerprint")) { if (!columnExists(db, TABLE_REPO, "fingerprint")) {
db.execSQL("alter table " + TABLE_REPO + " add column fingerprint text"); db.execSQL("alter table " + TABLE_REPO + " add column fingerprint text");
} }
@ -401,36 +407,41 @@ class DBHelper extends SQLiteOpenHelper {
db.update(TABLE_REPO, values, "address = ?", new String[] {repo.address}); db.update(TABLE_REPO, values, "address = ?", new String[] {repo.address});
} }
} }
}
private void addMaxAgeToRepo(SQLiteDatabase db, int oldVersion) { private void addMaxAgeToRepo(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 30 && !columnExists(db, TABLE_REPO, "maxage")) { if (oldVersion >= 30 || columnExists(db, TABLE_REPO, "maxage")) {
db.execSQL("alter table " + TABLE_REPO + " add column maxage integer not null default 0"); return;
} }
db.execSQL("alter table " + TABLE_REPO + " add column maxage integer not null default 0");
} }
private void addVersionToRepo(SQLiteDatabase db, int oldVersion) { private void addVersionToRepo(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 33 && !columnExists(db, TABLE_REPO, "version")) { if (oldVersion >= 33 || columnExists(db, TABLE_REPO, "version")) {
db.execSQL("alter table " + TABLE_REPO + " add column version integer not null default 0"); return;
} }
db.execSQL("alter table " + TABLE_REPO + " add column version integer not null default 0");
} }
private void addLastUpdatedToRepo(SQLiteDatabase db, int oldVersion) { private void addLastUpdatedToRepo(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 35 && !columnExists(db, TABLE_REPO, "lastUpdated")) { if (oldVersion >= 35 || columnExists(db, TABLE_REPO, "lastUpdated")) {
return;
}
Utils.debugLog(TAG, "Adding lastUpdated column to " + TABLE_REPO); Utils.debugLog(TAG, "Adding lastUpdated column to " + TABLE_REPO);
db.execSQL("Alter table " + TABLE_REPO + " add column lastUpdated string"); db.execSQL("Alter table " + TABLE_REPO + " add column lastUpdated string");
} }
}
private void addIsSwapToRepo(SQLiteDatabase db, int oldVersion) { private void addIsSwapToRepo(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 47 && !columnExists(db, TABLE_REPO, "isSwap")) { if (oldVersion >= 47 || columnExists(db, TABLE_REPO, "isSwap")) {
return;
}
Utils.debugLog(TAG, "Adding isSwap field to " + TABLE_REPO + " table in db."); Utils.debugLog(TAG, "Adding isSwap field to " + TABLE_REPO + " table in db.");
db.execSQL("alter table " + TABLE_REPO + " add column isSwap boolean default 0;"); db.execSQL("alter table " + TABLE_REPO + " add column isSwap boolean default 0;");
} }
}
private void addCredentialsToRepo(SQLiteDatabase db, int oldVersion) { private void addCredentialsToRepo(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 52) { if (oldVersion >= 52) {
return;
}
if (!columnExists(db, TABLE_REPO, "username")) { if (!columnExists(db, TABLE_REPO, "username")) {
Utils.debugLog(TAG, "Adding username field to " + TABLE_REPO + " table in db."); Utils.debugLog(TAG, "Adding username field to " + TABLE_REPO + " table in db.");
db.execSQL("alter table " + TABLE_REPO + " add column username string;"); db.execSQL("alter table " + TABLE_REPO + " add column username string;");
@ -441,49 +452,55 @@ class DBHelper extends SQLiteOpenHelper {
db.execSQL("alter table " + TABLE_REPO + " add column password string;"); db.execSQL("alter table " + TABLE_REPO + " add column password string;");
} }
} }
}
private void addChangelogToApp(SQLiteDatabase db, int oldVersion) { private void addChangelogToApp(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 48 && !columnExists(db, TABLE_APP, "changelogURL")) { if (oldVersion >= 48 || columnExists(db, TABLE_APP, "changelogURL")) {
return;
}
Utils.debugLog(TAG, "Adding changelogURL column to " + TABLE_APP); Utils.debugLog(TAG, "Adding changelogURL column to " + TABLE_APP);
db.execSQL("alter table " + TABLE_APP + " add column changelogURL text"); db.execSQL("alter table " + TABLE_APP + " add column changelogURL text");
} }
}
private void addIconUrlLargeToApp(SQLiteDatabase db, int oldVersion) { private void addIconUrlLargeToApp(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 49 && !columnExists(db, TABLE_APP, "iconUrlLarge")) { if (oldVersion >= 49 || columnExists(db, TABLE_APP, "iconUrlLarge")) {
return;
}
Utils.debugLog(TAG, "Adding iconUrlLarge columns to " + TABLE_APP); Utils.debugLog(TAG, "Adding iconUrlLarge columns to " + TABLE_APP);
db.execSQL("alter table " + TABLE_APP + " add column iconUrlLarge text"); db.execSQL("alter table " + TABLE_APP + " add column iconUrlLarge text");
} }
}
private void updateIconUrlLarge(SQLiteDatabase db, int oldVersion) { private void updateIconUrlLarge(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 50) { if (oldVersion >= 50) {
return;
}
Utils.debugLog(TAG, "Recalculating app icon URLs so that the newly added large icons will get updated."); Utils.debugLog(TAG, "Recalculating app icon URLs so that the newly added large icons will get updated.");
AppProvider.UpgradeHelper.updateIconUrls(context, db); AppProvider.UpgradeHelper.updateIconUrls(context, db);
clearRepoEtags(db); clearRepoEtags(db);
} }
}
private void addAuthorToApp(SQLiteDatabase db, int oldVersion) { private void addAuthorToApp(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 53 && !columnExists(db, TABLE_APP, "author")) { if (oldVersion >= 53) {
return;
}
if (!columnExists(db, TABLE_APP, "author")) {
Utils.debugLog(TAG, "Adding author column to " + TABLE_APP); Utils.debugLog(TAG, "Adding author column to " + TABLE_APP);
db.execSQL("alter table " + TABLE_APP + " add column author text"); db.execSQL("alter table " + TABLE_APP + " add column author text");
} }
if (oldVersion < 53 && !columnExists(db, TABLE_APP, "email")) { if (!columnExists(db, TABLE_APP, "email")) {
Utils.debugLog(TAG, "Adding email column to " + TABLE_APP); Utils.debugLog(TAG, "Adding email column to " + TABLE_APP);
db.execSQL("alter table " + TABLE_APP + " add column email text"); db.execSQL("alter table " + TABLE_APP + " add column email text");
} }
} }
private void useMaxValueInMaxSdkVersion(SQLiteDatabase db, int oldVersion) { private void useMaxValueInMaxSdkVersion(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 54) { if (oldVersion >= 54) {
return;
}
Utils.debugLog(TAG, "Converting maxSdkVersion value 0 to " + Byte.MAX_VALUE); Utils.debugLog(TAG, "Converting maxSdkVersion value 0 to " + Byte.MAX_VALUE);
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(ApkProvider.DataColumns.MAX_SDK_VERSION, Byte.MAX_VALUE); values.put(ApkProvider.DataColumns.MAX_SDK_VERSION, Byte.MAX_VALUE);
db.update(TABLE_APK, values, ApkProvider.DataColumns.MAX_SDK_VERSION + " < 1", null); db.update(TABLE_APK, values, ApkProvider.DataColumns.MAX_SDK_VERSION + " < 1", null);
} }
}
/** /**
* By clearing the etags stored in the repo table, it means that next time the user updates * By clearing the etags stored in the repo table, it means that next time the user updates
@ -501,7 +518,9 @@ class DBHelper extends SQLiteOpenHelper {
// was is specified by the user. We don't want to weely-neely nuke that data. // was is specified by the user. We don't want to weely-neely nuke that data.
// and the new way to deal with changes to the table structure is to add a // and the new way to deal with changes to the table structure is to add a
// if (oldVersion < x && !columnExists(...) and then alter the table as required. // if (oldVersion < x && !columnExists(...) and then alter the table as required.
if (oldVersion < 42) { if (oldVersion >= 42) {
return;
}
context.getSharedPreferences("FDroid", Context.MODE_PRIVATE).edit() context.getSharedPreferences("FDroid", Context.MODE_PRIVATE).edit()
.putBoolean("triedEmptyUpdate", false).commit(); .putBoolean("triedEmptyUpdate", false).commit();
db.execSQL("drop table " + TABLE_APP); db.execSQL("drop table " + TABLE_APP);
@ -509,7 +528,6 @@ class DBHelper extends SQLiteOpenHelper {
clearRepoEtags(db); clearRepoEtags(db);
createAppApk(db); createAppApk(db);
} }
}
private static void createAppApk(SQLiteDatabase db) { private static void createAppApk(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_APP); db.execSQL(CREATE_TABLE_APP);
@ -527,11 +545,12 @@ class DBHelper extends SQLiteOpenHelper {
// If any column was added or removed, just drop the table, create it // If any column was added or removed, just drop the table, create it
// again and let the cache be filled from scratch again. // again and let the cache be filled from scratch again.
private void recreateInstalledCache(SQLiteDatabase db, int oldVersion) { private void recreateInstalledCache(SQLiteDatabase db, int oldVersion) {
if (oldVersion < 51) { if (oldVersion >= 51) {
return;
}
db.execSQL(DROP_TABLE_INSTALLED_APP); db.execSQL(DROP_TABLE_INSTALLED_APP);
createInstalledApp(db); createInstalledApp(db);
} }
}
private static boolean columnExists(SQLiteDatabase db, private static boolean columnExists(SQLiteDatabase db,
String table, String column) { String table, String column) {

View File

@ -8,7 +8,6 @@ import android.net.Uri;
import android.os.RemoteException; import android.os.RemoteException;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log;
import org.fdroid.fdroid.CompatibilityChecker; import org.fdroid.fdroid.CompatibilityChecker;
import org.fdroid.fdroid.RepoUpdater; import org.fdroid.fdroid.RepoUpdater;
@ -99,7 +98,7 @@ public class RepoPersister {
} }
if (apksToSave.size() > 0 || appsToSave.size() > 0) { if (apksToSave.size() > 0 || appsToSave.size() > 0) {
Log.d(TAG, "Flushing details of up to " + MAX_APP_BUFFER + " apps and their packages to the database."); Utils.debugLog(TAG, "Flushing details of up to " + MAX_APP_BUFFER + " apps and their packages to the database.");
flushAppsToDbInBatch(); flushAppsToDbInBatch();
flushApksToDbInBatch(); flushApksToDbInBatch();
apksToSave.clear(); apksToSave.clear();

View File

@ -24,8 +24,8 @@ import android.content.Context;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.Signature; import android.content.pm.Signature;
import android.util.Log;
import org.fdroid.fdroid.Utils;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -58,9 +58,9 @@ public class ApkSignatureVerifier {
return true; return true;
} }
Log.d(TAG, "Signature mismatch!"); Utils.debugLog(TAG, "Signature mismatch!");
Log.d(TAG, "APK sig: " + Hex.toHexString(getApkSignature(apkFile))); Utils.debugLog(TAG, "APK sig: " + Hex.toHexString(getApkSignature(apkFile)));
Log.d(TAG, "F-Droid sig: " + Hex.toHexString(getFDroidSignature())); Utils.debugLog(TAG, "F-Droid sig: " + Hex.toHexString(getFDroidSignature()));
return false; return false;
} }

View File

@ -162,10 +162,7 @@ public abstract class Installer {
return false; return false;
} }
Hasher hasher = new Hasher(hashType, apkFile); Hasher hasher = new Hasher(hashType, apkFile);
if (hasher != null && hasher.match(hash)) { return hasher.match(hash);
return true;
}
return false;
} }
/** /**

View File

@ -76,7 +76,7 @@ public class PrivilegedInstaller extends Installer {
private static final String PRIVILEGED_EXTENSION_SERVICE_INTENT = "org.fdroid.fdroid.privileged.IPrivilegedService"; private static final String PRIVILEGED_EXTENSION_SERVICE_INTENT = "org.fdroid.fdroid.privileged.IPrivilegedService";
public static final String PRIVILEGED_EXTENSION_PACKAGE_NAME = "org.fdroid.fdroid.privileged"; public static final String PRIVILEGED_EXTENSION_PACKAGE_NAME = "org.fdroid.fdroid.privileged";
private Activity mActivity; private final Activity mActivity;
private static final int REQUEST_CONFIRM_PERMS = 0; private static final int REQUEST_CONFIRM_PERMS = 0;

View File

@ -91,10 +91,6 @@ public class SwapService extends Service {
@NonNull @NonNull
private final Set<String> appsToSwap = new HashSet<>(); private final Set<String> appsToSwap = new HashSet<>();
public SwapService() {
super();
}
/** /**
* Where relevant, the state of the swap process will be saved to disk using preferences. * Where relevant, the state of the swap process will be saved to disk using preferences.
* Note that this is not always useful, for example saving the "current wifi network" is * Note that this is not always useful, for example saving the "current wifi network" is

View File

@ -22,7 +22,6 @@ public final class BluetoothSwap extends SwapType {
@NonNull @NonNull
private final BluetoothAdapter adapter; private final BluetoothAdapter adapter;
private BroadcastReceiver receiver;
private boolean isDiscoverable; private boolean isDiscoverable;
@Nullable @Nullable
@ -64,7 +63,7 @@ public final class BluetoothSwap extends SwapType {
return; return;
} }
receiver = new BroadcastReceiver() { BroadcastReceiver receiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
switch (intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, -1)) { switch (intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, -1)) {

View File

@ -94,7 +94,7 @@ public class DownloaderService extends Service {
private static volatile Downloader downloader; private static volatile Downloader downloader;
private LocalBroadcastManager localBroadcastManager; private LocalBroadcastManager localBroadcastManager;
private static final HashMap<String, Integer> QUEUE_WHATS = new HashMap<String, Integer>(); private static final HashMap<String, Integer> QUEUE_WHATS = new HashMap<>();
private int what; private int what;
private final class ServiceHandler extends Handler { private final class ServiceHandler extends Handler {

View File

@ -221,7 +221,7 @@ public class LocalHTTPD extends NanoHTTPD {
try { try {
// Calculate etag // Calculate etag
String etag = Integer String etag = Integer
.toHexString((file.getAbsolutePath() + file.lastModified() + "" + file.length()) .toHexString((file.getAbsolutePath() + file.lastModified() + String.valueOf(file.length()))
.hashCode()); .hashCode());
// Support (simple) skipping: // Support (simple) skipping:
@ -268,7 +268,7 @@ public class LocalHTTPD extends NanoHTTPD {
fis.skip(startFrom); fis.skip(startFrom);
res = createResponse(Response.Status.PARTIAL_CONTENT, mime, fis); res = createResponse(Response.Status.PARTIAL_CONTENT, mime, fis);
res.addHeader("Content-Length", "" + dataLen); res.addHeader("Content-Length", String.valueOf(dataLen));
res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/"
+ fileLen); + fileLen);
res.addHeader("ETag", etag); res.addHeader("ETag", etag);
@ -278,7 +278,7 @@ public class LocalHTTPD extends NanoHTTPD {
res = createResponse(Response.Status.NOT_MODIFIED, mime, ""); res = createResponse(Response.Status.NOT_MODIFIED, mime, "");
} else { } else {
res = createResponse(Response.Status.OK, mime, new FileInputStream(file)); res = createResponse(Response.Status.OK, mime, new FileInputStream(file));
res.addHeader("Content-Length", "" + fileLen); res.addHeader("Content-Length", String.valueOf(fileLen));
res.addHeader("ETag", etag); res.addHeader("ETag", etag);
} }
} }

View File

@ -259,7 +259,7 @@ public class BluetoothServer extends Thread {
try { try {
// Calculate etag // Calculate etag
String etag = Integer String etag = Integer
.toHexString((file.getAbsolutePath() + file.lastModified() + "" + file.length()) .toHexString((file.getAbsolutePath() + file.lastModified() + String.valueOf(file.length()))
.hashCode()); .hashCode());
// Support (simple) skipping: // Support (simple) skipping:
@ -306,7 +306,7 @@ public class BluetoothServer extends Thread {
fis.skip(startFrom); fis.skip(startFrom);
res = createResponse(NanoHTTPD.Response.Status.PARTIAL_CONTENT, mime, fis); res = createResponse(NanoHTTPD.Response.Status.PARTIAL_CONTENT, mime, fis);
res.addHeader("Content-Length", "" + dataLen); res.addHeader("Content-Length", String.valueOf(dataLen));
res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/"
+ fileLen); + fileLen);
res.addHeader("ETag", etag); res.addHeader("ETag", etag);
@ -316,7 +316,7 @@ public class BluetoothServer extends Thread {
res = createResponse(NanoHTTPD.Response.Status.NOT_MODIFIED, mime, ""); res = createResponse(NanoHTTPD.Response.Status.NOT_MODIFIED, mime, "");
} else { } else {
res = createResponse(NanoHTTPD.Response.Status.OK, mime, new FileInputStream(file)); res = createResponse(NanoHTTPD.Response.Status.OK, mime, new FileInputStream(file));
res.addHeader("Content-Length", "" + fileLen); res.addHeader("Content-Length", String.valueOf(fileLen));
res.addHeader("ETag", etag); res.addHeader("ETag", etag);
} }
} }

View File

@ -328,9 +328,6 @@ public class InstallExtensionDialogActivity extends FragmentActivity {
* 3. Verify that install worked * 3. Verify that install worked
*/ */
private void postInstall() { private void postInstall() {
// hack to get theme applied (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(this, FDroidApp.getCurThemeResId());
int isInstalledCorrectly = int isInstalledCorrectly =
PrivilegedInstaller.isExtensionInstalledCorrectly(this); PrivilegedInstaller.isExtensionInstalledCorrectly(this);
@ -367,6 +364,9 @@ public class InstallExtensionDialogActivity extends FragmentActivity {
throw new RuntimeException("unhandled return"); throw new RuntimeException("unhandled return");
} }
// hack to get theme applied (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(this, FDroidApp.getCurThemeResId());
AlertDialog.Builder builder = new AlertDialog.Builder(theme) AlertDialog.Builder builder = new AlertDialog.Builder(theme)
.setTitle(title) .setTitle(title)
.setMessage(message) .setMessage(message)

View File

@ -420,16 +420,14 @@ public class AppSecurityPermissions {
final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
final boolean isNormal = base == PermissionInfo.PROTECTION_NORMAL; final boolean isNormal = base == PermissionInfo.PROTECTION_NORMAL;
final boolean isDangerous = base == PermissionInfo.PROTECTION_DANGEROUS; final boolean isDangerous = base == PermissionInfo.PROTECTION_DANGEROUS;
final boolean wasGranted =
(existingReqFlags & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
// Dangerous and normal permissions are always shown to the user // Dangerous and normal permissions are always shown to the user
if (isNormal || isDangerous) { if (isNormal || isDangerous) {
return true; return true;
} }
final boolean isDevelopment = final boolean isDevelopment = (pInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0;
(pInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0; final boolean wasGranted = (existingReqFlags & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
// Development permissions are only shown to the user if they are already // Development permissions are only shown to the user if they are already
// granted to the app -- if we are installing an app and they are not // granted to the app -- if we are installing an app and they are not

View File

@ -40,6 +40,7 @@ public class CaffeinatedScrollView extends ScrollView {
/** /**
* Make this visible so we can call it * Make this visible so we can call it
*/ */
@SuppressWarnings("PMD.UselessOverridingMethod")
@Override @Override
public boolean awakenScrollBars() { public boolean awakenScrollBars() {
return super.awakenScrollBars(); return super.awakenScrollBars();

30
config/pmd/rules.xml Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0"?>
<ruleset name="Custom ruleset"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<!--<rule ref="rulesets/java/basic.xml"/>-->
<rule ref="rulesets/java/unusedcode.xml"/>
<rule ref="rulesets/java/android.xml"/>
<rule ref="rulesets/java/clone.xml"/>
<rule ref="rulesets/java/finalizers.xml"/>
<rule ref="rulesets/java/imports.xml"/>
<rule ref="rulesets/java/migrating.xml"/>
<rule ref="rulesets/java/unnecessary.xml">
<exclude name="UselessParentheses"/> <!--Too nitpicky-->
</rule>
<rule ref="rulesets/java/optimizations.xml/PrematureDeclaration"/>
<rule ref="rulesets/java/optimizations.xml/AddEmptyString"/>
<rule ref="rulesets/java/controversial.xml/UnnecessaryConstructor"/>
<rule ref="rulesets/java/design.xml/FinalFieldCouldBeStatic"/>
<rule ref="rulesets/java/design.xml/CloseResource"/>
<rule ref="rulesets/java/design.xml/DefaultLabelNotLastInSwitchStmt"/>
<rule ref="rulesets/java/design.xml/UnnecessaryLocalBeforeReturn"/>
<rule ref="rulesets/java/design.xml/NonCaseLabelInSwitchStatement"/>
<rule ref="rulesets/java/design.xml/EqualsNull"/>
<rule ref="rulesets/java/design.xml/IdempotentOperations"/>
<rule ref="rulesets/java/design.xml/ImmutableField"/>
<rule ref="rulesets/java/design.xml/SingularField"/>
</ruleset>