Skip to content

Commit c25e643

Browse files
authored
Merge pull request #371 from magnusja/develop
core v0.9.2 libusbcommunication v0.2.3
2 parents 51e6f60 + 0d290bb commit c25e643

File tree

24 files changed

+158
-58
lines changed

24 files changed

+158
-58
lines changed

.github/workflows/android.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ jobs:
1414
with:
1515
java-version: 1.11
1616
- name: install libusb
17-
run: wget https://github.com/libusb/libusb/archive/v1.0.24.zip && unzip v1.0.24.zip
17+
run: wget https://github.com/libusb/libusb/archive/v1.0.26.zip && unzip v1.0.26.zip
1818
- name: write local properties
19-
run: echo "libusb.dir=$GITHUB_WORKSPACE/libusb-1.0.24" > $GITHUB_WORKSPACE/local.properties
19+
run: echo "libusb.dir=$GITHUB_WORKSPACE/libusb-1.0.26" > $GITHUB_WORKSPACE/local.properties
2020
- name: Build & test with Gradle
2121
run: ./gradlew jacocoTestReport --stacktrace
2222
- name: codecov

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ A library to access USB mass storage devices (pen drives, external HDDs, card re
1313
The library can be included into your project like this:
1414

1515
```ruby
16-
implementation 'me.jahnen.libaums:core:0.9.1'
16+
implementation 'me.jahnen.libaums:core:0.9.2'
1717
```
1818

1919
If you need the HTTP or the storage provider module:
@@ -93,7 +93,7 @@ UsbFile root = currentFs.getRootDirectory();
9393
UsbFile[] files = root.listFiles();
9494
for(UsbFile file: files) {
9595
Log.d(TAG, file.getName());
96-
if(file.isDirectory()) {
96+
if(!file.isDirectory()) {
9797
Log.d(TAG, file.getLength());
9898
}
9999
}

androidtests/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ android {
2929
useLibrary 'android.test.runner'
3030
useLibrary 'android.test.base'
3131
useLibrary 'android.test.mock'
32+
namespace 'me.jahnen.libaums.core.androidtests'
3233
}
3334

3435
dependencies {
+1-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="me.jahnen.libaums.core.androidtests">
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
32
</manifest>

app/build.gradle

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ android {
1818
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
1919
}
2020
}
21-
22-
lintOptions {
21+
lint {
2322
abortOnError false
2423
}
24+
namespace 'me.jahnen.libaums.core.usbfileman'
25+
2526
}
2627

2728
dependencies {

app/src/main/AndroidManifest.xml

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
*/
1818
-->
1919
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
20-
xmlns:tools="http://schemas.android.com/tools"
21-
package="me.jahnen.libaums.core.usbfileman" >
20+
xmlns:tools="http://schemas.android.com/tools">
2221

2322
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2423
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

build.gradle

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
// Top-level build file where you can add configuration options common to all sub-projects/modules.
22

33
buildscript {
4-
ext.kotlin_version = '1.6.10'
4+
ext.kotlin_version = '1.8.0'
55
repositories {
66
mavenCentral()
77
maven { url "https://plugins.gradle.org/m2/" }
88
google()
99
}
1010
dependencies {
11-
classpath 'com.android.tools.build:gradle:7.0.4'
11+
classpath 'com.android.tools.build:gradle:7.4.2'
1212

1313
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
1414
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
1515

1616
classpath 'org.codehaus.groovy:groovy-all:2.4.15'
1717
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1818

19-
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.10"
20-
classpath "org.jacoco:org.jacoco.core:0.8.7"
19+
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.8.10"
20+
classpath "org.jacoco:org.jacoco.core:0.8.8"
2121
classpath 'com.dicedmelon.gradle:jacoco-android:0.1.5'
22-
classpath 'io.github.gradle-nexus:publish-plugin:1.1.0'
22+
classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
2323
// NOTE: Do not place your application dependencies here; they belong
2424
// in the individual module build.gradle files
2525
}
+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Wed Sep 11 11:27:30 CEST 2019
1+
#Tue Nov 22 10:59:55 CET 2022
22
distributionBase=GRADLE_USER_HOME
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
34
distributionPath=wrapper/dists
4-
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
6+
zipStoreBase=GRADLE_USER_HOME

httpserver/build.gradle

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ android {
3030
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
3131
}
3232
}
33-
lintOptions {
33+
lint {
3434
abortOnError false
3535
}
36+
namespace 'me.jahnen.libaums.core.httpserver'
3637
}
3738

3839

httpserver/src/main/AndroidManifest.xml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="me.jahnen.libaums.core.httpserver">
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
32

43
<uses-permission android:name="android.permission.INTERNET" />
54

javafs/build.gradle

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ android {
1717
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
1818
}
1919
}
20-
lintOptions {
20+
lint {
2121
abortOnError false
2222
}
23+
namespace 'me.jahnen.libaums.javafs'
2324
}
2425

2526
dependencies {

javafs/src/main/AndroidManifest.xml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="me.jahnen.libaums.javafs">
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
32

43
<application android:allowBackup="true"
54
android:supportsRtl="true">

libaums/build.gradle

+11-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jacoco {
99

1010
ext {
1111
PUBLISH_GROUP_ID = 'me.jahnen.libaums'
12-
PUBLISH_VERSION = '0.9.1'
12+
PUBLISH_VERSION = '0.9.2'
1313
PUBLISH_ARTIFACT_ID = 'core'
1414
}
1515

@@ -44,9 +44,6 @@ android {
4444
}
4545
}
4646

47-
lintOptions {
48-
abortOnError false
49-
}
5047

5148
// TODO remove this?
5249
testOptions {
@@ -66,21 +63,25 @@ android {
6663
path "CMakeLists.txt"
6764
}
6865

69-
ndkVersion '23.1.7779620'
66+
ndkVersion '25.2.9519653'
67+
}
68+
lint {
69+
abortOnError false
7070
}
71+
namespace 'me.jahnen.libaums.core'
7172
}
7273

7374
dependencies {
74-
testImplementation 'junit:junit:4.13'
75+
testImplementation 'junit:junit:4.13.1'
7576
testImplementation 'org.apache.commons:commons-io:1.3.2'
7677
testImplementation 'com.eclipsesource.minimal-json:minimal-json:0.9.4'
7778
testImplementation 'org.xenei:junit-contracts:0.1.7'
7879
testImplementation 'org.mockito:mockito-core:2.28.2'
7980

80-
api 'androidx.annotation:annotation:1.3.0'
81-
javadocDeps 'androidx.annotation:annotation:1.3.0'
82-
api 'androidx.core:core:1.8.0-alpha01'
83-
api "androidx.core:core-ktx:1.7.0"
81+
api 'androidx.annotation:annotation:1.6.0'
82+
javadocDeps 'androidx.annotation:annotation:1.6.0'
83+
api 'androidx.core:core:1.12.0-alpha01'
84+
api "androidx.core:core-ktx:1.9.0"
8485
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
8586
}
8687

libaums/src/main/AndroidManifest.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
* limitations under the License.
1616
*/
1717
-->
18-
<manifest package="me.jahnen.libaums.core">
18+
<manifest>
1919

2020
</manifest>

libaums/src/main/java/me/jahnen/libaums/core/UsbMassStorageDevice.kt

+4-2
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,10 @@ private constructor(private val usbManager: UsbManager,
168168
* or write from or to the partitions returned by [.getPartitions].
169169
*/
170170
fun close() {
171-
usbCommunication.close()
172-
inited = false
171+
if (inited) {
172+
usbCommunication.close()
173+
inited = false
174+
}
173175
}
174176

175177
companion object {

libaums/src/main/java/me/jahnen/libaums/core/driver/scsi/ScsiBlockDevice.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class ScsiBlockDevice(private val usbCommunication: UsbCommunication, private va
5656
*
5757
* @return The block device size in blocks
5858
*/
59-
override val blocks: Long = lastBlockAddress.toLong()
59+
override val blocks: Long get() = lastBlockAddress.toLong()
6060

6161
/**
6262
* Issues a SCSI Inquiry to determine the connected device. After that it is

libaums/src/main/java/me/jahnen/libaums/core/fs/FileSystemFactory.kt

+45-6
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,20 @@ import java.util.*
3131
* @author mjahnen
3232
*/
3333
object FileSystemFactory {
34+
private data class PrioritizedFileSystemCreator(val priority: Int, val count: Int, val creator: FileSystemCreator)
35+
36+
private var count = 0
37+
private val fileSystems = TreeSet(
38+
compareBy<PrioritizedFileSystemCreator> { it.priority }.thenBy { it.count }
39+
)
40+
41+
/**
42+
* The default priority of a creator registered with the file system. Creators will be evaluated
43+
* in order from lowest priority number to highest priority number. If two creators are
44+
* registered with the same priority then the one inserted first will be evaluated first.
45+
*/
46+
const val DEFAULT_PRIORITY = 0
3447

35-
private val fileSystems = ArrayList<FileSystemCreator>()
3648
/**
3749
* Set the timezone a file system should use to decode timestamps, if the file system only stores
3850
* local date and time and has no reference which zone these timestamp correspond to. (True for
@@ -45,14 +57,15 @@ object FileSystemFactory {
4557
class UnsupportedFileSystemException : IOException()
4658

4759
init {
48-
registerFileSystem(Fat32FileSystemCreator())
60+
registerFileSystem(Fat32FileSystemCreator(), DEFAULT_PRIORITY + 1)
4961
}
5062

63+
@Synchronized
5164
@Throws(IOException::class, FileSystemFactory.UnsupportedFileSystemException::class)
5265
fun createFileSystem(entry: PartitionTableEntry,
5366
blockDevice: BlockDeviceDriver): FileSystem {
54-
for (creator in fileSystems) {
55-
val fs = creator.read(entry, blockDevice)
67+
fileSystems.forEach {
68+
val fs = it.creator.read(entry, blockDevice)
5669
if (fs != null) {
5770
return fs
5871
}
@@ -62,14 +75,40 @@ object FileSystemFactory {
6275
}
6376

6477
/**
65-
* Register a new file system.
78+
* Register a new file system at the default priority.
6679
* @param creator The creator which is able to check if a [BlockDeviceDriver] is holding
6780
* the correct type of file system and is able to instantiate a [FileSystem]
6881
* instance.
6982
*/
7083
@Synchronized
7184
@JvmStatic
7285
fun registerFileSystem(creator: FileSystemCreator) {
73-
fileSystems.add(creator)
86+
registerFileSystem(creator, DEFAULT_PRIORITY)
87+
}
88+
89+
/**
90+
* Register a new file system with the given priority.
91+
* @param creator The creator which is able to check if a [BlockDeviceDriver] is holding
92+
* the correct type of file system and is able to instantiate a [FileSystem]
93+
* instance.
94+
*
95+
* @param priority The priority this file system creator has when attempting to
96+
* create a file system.
97+
*/
98+
@Synchronized
99+
@JvmStatic
100+
fun registerFileSystem(creator: FileSystemCreator, priority: Int) {
101+
fileSystems.add(PrioritizedFileSystemCreator(priority, count++, creator))
74102
}
103+
104+
105+
/**
106+
* Removes all registered file systems.
107+
*/
108+
@Synchronized
109+
@JvmStatic
110+
fun clearFileSystems() {
111+
fileSystems.clear()
112+
}
113+
75114
}

libaums/src/test/java/me/jahnen/libaums/core/fs/FileSystemFactoryTest.java

+49-5
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
import me.jahnen.libaums.core.driver.ByteBlockDevice;
55
import me.jahnen.libaums.core.driver.file.FileBlockDeviceDriver;
66
import me.jahnen.libaums.core.fs.fat32.Fat32FileSystem;
7+
import me.jahnen.libaums.core.fs.fat32.Fat32FileSystemCreator;
78
import me.jahnen.libaums.core.partition.PartitionTableEntry;
89
import me.jahnen.libaums.core.partition.PartitionTypes;
910

1011
import org.junit.Test;
11-
1212
import java.net.URL;
13+
import java.util.ArrayList;
14+
import java.util.Arrays;
1315

16+
import static org.junit.Assert.assertEquals;
1417
import static org.junit.Assert.assertTrue;
1518

1619
/**
@@ -19,15 +22,56 @@
1922
public class FileSystemFactoryTest {
2023
@Test
2124
public void createFat32FileSystem() throws Exception {
25+
BlockDeviceDriver blockDevice = createDevice();
26+
PartitionTableEntry entry = createPartitionTable();
27+
FileSystem fs = FileSystemFactory.INSTANCE.createFileSystem(entry, blockDevice);
28+
29+
assertTrue(fs instanceof Fat32FileSystem);
30+
}
31+
32+
@Test
33+
public void fileSystemPriority() throws Exception {
34+
ArrayList<String> orderTracker = new ArrayList<>();
35+
36+
// Clear and register with varying priorities to verify creators are invoked in expected order
37+
FileSystemFactory.clearFileSystems();
38+
FileSystemFactory.registerFileSystem(mockCreator(orderTracker,"not called"), FileSystemFactory.DEFAULT_PRIORITY + 4);
39+
FileSystemFactory.registerFileSystem(mockCreator(orderTracker,"third"), FileSystemFactory.DEFAULT_PRIORITY + 1);
40+
FileSystemFactory.registerFileSystem(mockCreator(orderTracker,"first"));
41+
FileSystemFactory.registerFileSystem(mockCreator(orderTracker,"fourth"), FileSystemFactory.DEFAULT_PRIORITY + 2);
42+
FileSystemFactory.registerFileSystem(mockCreator(orderTracker,"second"));
43+
FileSystemFactory.registerFileSystem(new Fat32FileSystemCreator(), FileSystemFactory.DEFAULT_PRIORITY + 3);
44+
FileSystemFactory.registerFileSystem(mockCreator(orderTracker,"not called"), FileSystemFactory.DEFAULT_PRIORITY + 5);
45+
46+
BlockDeviceDriver blockDevice = createDevice();
47+
PartitionTableEntry entry = createPartitionTable();
48+
FileSystem fs = FileSystemFactory.INSTANCE.createFileSystem(entry, blockDevice);
49+
50+
assertEquals(orderTracker, Arrays.asList("first", "second", "third", "fourth"));
51+
assertTrue(fs instanceof Fat32FileSystem);
52+
53+
// Since this is a singleton try to return it to its original state for other tests
54+
FileSystemFactory.clearFileSystems();
55+
FileSystemFactory.registerFileSystem(new Fat32FileSystemCreator(), FileSystemFactory.DEFAULT_PRIORITY + 1);
56+
}
57+
58+
private FileSystemCreator mockCreator(ArrayList<String> orderTracker, String name) {
59+
return (entry, blockDevice) -> {
60+
orderTracker.add(name);
61+
return null;
62+
};
63+
}
64+
65+
private BlockDeviceDriver createDevice() throws Exception {
2266
BlockDeviceDriver blockDevice = new ByteBlockDevice(new FileBlockDeviceDriver(
2367
new URL("https://www.dropbox.com/s/3bxngiqmwitlucd/mbr_fat32.img?dl=1"),
2468
2 * 512));
2569
blockDevice.init();
2670

27-
PartitionTableEntry entry = new PartitionTableEntry(PartitionTypes.FAT32, 2 * 512, 1337);
28-
FileSystem fs = FileSystemFactory.INSTANCE.createFileSystem(entry, blockDevice);
29-
30-
assertTrue(fs instanceof Fat32FileSystem);
71+
return blockDevice;
3172
}
3273

74+
private PartitionTableEntry createPartitionTable() {
75+
return new PartitionTableEntry(PartitionTypes.FAT32, 2 * 512, 1337);
76+
}
3377
}

0 commit comments

Comments
 (0)