forked from organicmaps/organicmaps
Compare commits
4 commits
master
...
pastk-andr
Author | SHA1 | Date | |
---|---|---|---|
21055f24f5 | |||
01a3e0b456 | |||
6278efaf44 | |||
8947380197 |
4 changed files with 61 additions and 63 deletions
|
@ -1036,6 +1036,12 @@ Java_com_mapswithme_maps_Framework_nativeGetSettingsDir(JNIEnv * env, jclass)
|
|||
return jni::ToJavaString(env, GetPlatform().SettingsDir().c_str());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_maps_Framework_nativeGetDataFileExt(JNIEnv * env, jclass)
|
||||
{
|
||||
return jni::ToJavaString(env, DATA_FILE_EXTENSION);
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_com_mapswithme_maps_Framework_nativeGetMovableFilesExts(JNIEnv * env, jclass)
|
||||
{
|
||||
|
|
|
@ -212,6 +212,8 @@ public class Framework
|
|||
|
||||
public static native void nativeDeactivatePopup();
|
||||
|
||||
public static native String nativeGetDataFileExt();
|
||||
|
||||
public static native String[] nativeGetMovableFilesExts();
|
||||
|
||||
public static native String[] nativeGetBookmarksFilesExts();
|
||||
|
|
|
@ -32,6 +32,7 @@ public class StoragePathManager
|
|||
{
|
||||
static final String TAG = StoragePathManager.class.getName();
|
||||
private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.STORAGE);
|
||||
private static final String DATA_FILE_EXT = Framework.nativeGetDataFileExt();
|
||||
private static final String[] MOVABLE_EXTS = Framework.nativeGetMovableFilesExts();
|
||||
static final FilenameFilter MOVABLE_FILES_FILTER = (dir, filename) -> {
|
||||
for (String ext : MOVABLE_EXTS)
|
||||
|
@ -52,7 +53,7 @@ public class StoragePathManager
|
|||
|
||||
public final List<StorageItem> mStorages = new ArrayList<>();
|
||||
public int mCurrentStorageIndex = -1;
|
||||
private StorageItem mEmulatedStorage = null;
|
||||
private StorageItem mInternalStorage = null;
|
||||
|
||||
public StoragePathManager(@NonNull Context context)
|
||||
{
|
||||
|
@ -118,8 +119,6 @@ public class StoragePathManager
|
|||
|
||||
/**
|
||||
* Adds a storage into the list if it passes sanity checks.
|
||||
* Internal storage is omitted if it backs an emulated one (unless internal is the current one),
|
||||
* hence internal should be fed to this method last.
|
||||
*/
|
||||
private void addStorageOption(File dir, boolean isInternal, String configPath)
|
||||
{
|
||||
|
@ -147,20 +146,27 @@ public class StoragePathManager
|
|||
(isInternal ? "internal" : "external") + ", " +
|
||||
freeSize + " available out of " + totalSize + " bytes";
|
||||
|
||||
// Check if internal and emulated are the same physical device.
|
||||
// Allow for some divergence in freeSize because there could have been file operations inbetween free space checks.
|
||||
if (isInternal && mEmulatedStorage != null && mEmulatedStorage.mTotalSize == totalSize
|
||||
&& mEmulatedStorage.mFreeSize > freeSize - 1024 * 1024
|
||||
&& mEmulatedStorage.mFreeSize < freeSize + 1024 * 1024)
|
||||
/**
|
||||
Removal of a second condition ("&& mEmulatedStorage.mFreeSize < 0") or a whole "if" block
|
||||
leads to a VerifyError on Android 5 reproducible in android emulator using Nexus S API 21
|
||||
with an Android 5.0 x86_64 AOSP (w/o Google APIs) image (also on a Honor 4C with Android 5.1.1).
|
||||
Log:
|
||||
I/art: Verification error in void com.mapswithme.maps.settings.StoragePathManager.addStorageOption(java.io.File, boolean, java.lang.String)
|
||||
I/art: couldn't find method android.os.storage.StorageManager.getStorageVolume (Ljava/io/File;)Landroid/os/storage/StorageVolume;
|
||||
I/art: void com.mapswithme.maps.settings.StoragePathManager.addStorageOption(java.io.File, boolean, java.lang.String) failed to verify: Set register to unknown type ConflictragePathManager.addStorageOption(java.io.File, boolean, java.lang.String): [0x109]
|
||||
I/art:
|
||||
E/art: Verification failed on class com.mapswithme.maps.settings.StoragePathManager in /data/app/app.organicmaps.beta-2/base.apk because: Verifier rejected class com.mapswithme.maps.settings.StoragePathManager due to bad method void com.mapswithme.maps.settings.StoragePathManager.addStorageOption(java.io.File, boolean, java.lang.String)
|
||||
D/AndroidRuntime: Shutting down VM
|
||||
E/AndroidRuntime: FATAL EXCEPTION: main
|
||||
Process: app.organicmaps.beta, PID: 7188
|
||||
java.lang.VerifyError: Verifier rejected class com.mapswithme.maps.settings.StoragePathManager due to bad method void com.mapswithme.maps.settings.StoragePathManager.addStorageOption(java.io.File, boolean, java.lang.String) (declaration of 'com.mapswithme.maps.settings.StoragePathManager' appears in /data/app/app.organicmaps.beta-2/base.apk)
|
||||
*/
|
||||
if (
|
||||
mInternalStorage != null
|
||||
&& mInternalStorage.mFreeSize < 0
|
||||
)
|
||||
{
|
||||
final String emulated = ", backs emulated (" + mEmulatedStorage.mPath + ")";
|
||||
// Allow duplicating internal storage if its the current one (for migration purposes).
|
||||
if (!isCurrent)
|
||||
{
|
||||
LOGGER.i(TAG, "Duplicate" + emulated + ": " + commentedPath);
|
||||
return;
|
||||
}
|
||||
commentedPath += emulated;
|
||||
commentedPath += " *VerifyError test case*";
|
||||
}
|
||||
|
||||
boolean isEmulated = false;
|
||||
|
@ -245,8 +251,8 @@ public class StoragePathManager
|
|||
mStorages.add(storage);
|
||||
if (isCurrent)
|
||||
mCurrentStorageIndex = mStorages.size() - 1;
|
||||
if (isEmulated)
|
||||
mEmulatedStorage = storage;
|
||||
if (isInternal)
|
||||
mInternalStorage = storage;
|
||||
LOGGER.i(TAG, "Accepted " + commentedPath);
|
||||
}
|
||||
catch (SecurityException | IOException ex)
|
||||
|
@ -267,7 +273,7 @@ public class StoragePathManager
|
|||
LOGGER.i(TAG, "Begin scanning storages");
|
||||
mStorages.clear();
|
||||
mCurrentStorageIndex = -1;
|
||||
mEmulatedStorage = null;
|
||||
mInternalStorage = null;
|
||||
|
||||
// External storages (SD cards and other).
|
||||
for (File externalDir : mContext.getExternalFilesDirs(null))
|
||||
|
@ -291,57 +297,34 @@ public class StoragePathManager
|
|||
}
|
||||
|
||||
/**
|
||||
* Determine whether the storage contains map files
|
||||
* by checking for non-empty directories with version-like names (e.g. "220415").
|
||||
* Determine whether the storage contains map files.
|
||||
*/
|
||||
private static boolean containsMapData(String storagePath)
|
||||
{
|
||||
File path = new File(storagePath);
|
||||
File[] candidates = path.listFiles((pathname) -> {
|
||||
if (!pathname.isDirectory())
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
String name = pathname.getName();
|
||||
if (name.length() != 6)
|
||||
return false;
|
||||
|
||||
int version = Integer.valueOf(name);
|
||||
return (version > 120000 && version <= 999999);
|
||||
}
|
||||
catch (NumberFormatException ignored)
|
||||
{
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return (candidates != null && candidates.length > 0 &&
|
||||
candidates[0].list().length > 0);
|
||||
return StorageUtils.getDirSizeRecursively(new File(storagePath), (dir, filename) -> filename.endsWith(DATA_FILE_EXT)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get storage with the most free space.
|
||||
* Get a writable non-internal storage with the most free space.
|
||||
* Returns an internal storage if no other options are suitable.
|
||||
*/
|
||||
public StorageItem getBiggestStorage()
|
||||
public StorageItem getDefaultStorage()
|
||||
{
|
||||
StorageItem res = null;
|
||||
for (StorageItem storage : mStorages)
|
||||
{
|
||||
if (res == null || res.mFreeSize < storage.mFreeSize)
|
||||
{
|
||||
if ((res == null || res.mFreeSize < storage.mFreeSize)
|
||||
&& storage.mIsReadonly == false && !storage.equals(mInternalStorage))
|
||||
res = storage;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
return res != null ? res : mInternalStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an available storage with existing maps files.
|
||||
* Checks the currently configured storage first,
|
||||
* then scans other storages. If no maps files found
|
||||
* defaults to the storage with the most free space.
|
||||
* Checks the currently configured storage first, then scans other storages.
|
||||
* If no map files found uses getDefaultStorage().
|
||||
*/
|
||||
public static String findMapsStorage(@NonNull Application application)
|
||||
{
|
||||
|
@ -382,8 +365,8 @@ public class StoragePathManager
|
|||
}
|
||||
}
|
||||
|
||||
path = mgr.getBiggestStorage().mPath;
|
||||
LOGGER.i(TAG, "Defaulting to a storage with the most free space: " + path);
|
||||
path = mgr.getDefaultStorage().mPath;
|
||||
LOGGER.i(TAG, "Using default storage " + path);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
|
|
@ -252,17 +252,24 @@ public class StorageUtils
|
|||
|
||||
public static long getDirSizeRecursively(File file, FilenameFilter fileFilter)
|
||||
{
|
||||
if (file.isDirectory())
|
||||
try
|
||||
{
|
||||
long dirSize = 0;
|
||||
for (File child : file.listFiles())
|
||||
dirSize += getDirSizeRecursively(child, fileFilter);
|
||||
if (file.isDirectory())
|
||||
{
|
||||
long dirSize = 0;
|
||||
for (File child : file.listFiles())
|
||||
dirSize += getDirSizeRecursively(child, fileFilter);
|
||||
|
||||
return dirSize;
|
||||
return dirSize;
|
||||
}
|
||||
|
||||
if (fileFilter.accept(file.getParentFile(), file.getName()))
|
||||
return file.length();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.e(TAG, "Can't calculate file or directory size", e);
|
||||
}
|
||||
|
||||
if (fileFilter.accept(file.getParentFile(), file.getName()))
|
||||
return file.length();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue