/*
* Created by Angel Leon (@gubatron), Alden Torres (aldenml)
* Copyright (c) 2011-2014, FrostWire(R). All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.bt.download.android.util;
import static android.content.Context.ACTIVITY_SERVICE;
import static android.content.pm.ApplicationInfo.FLAG_LARGE_HEAP;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.support.v4.content.ContextCompat;
import android.support.v4.os.EnvironmentCompat;
import com.frostwire.logging.Logger;
/**
*
* @author gubatron
* @author aldenml
*
*/
public final class SystemUtils {
private static final Logger LOG = Logger.getLogger(SystemUtils.class);
private static final int VERSION_CODE_JELLY_BEAN = 16;
private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18;
private static final int VERSION_CODE_KITKAT = 19;
private SystemUtils() {
}
public static File getCacheDir(Context context, String directory) {
File cache;
if (isPrimaryExternalStorageMounted()) {
cache = context.getExternalCacheDir();
} else {
cache = context.getCacheDir();
}
return new File(cache, directory);
}
public static int calculateMemoryCacheSize(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
boolean largeHeap = (context.getApplicationInfo().flags & FLAG_LARGE_HEAP) != 0;
int memoryClass = am.getMemoryClass();
if (largeHeap) {
memoryClass = am.getLargeMemoryClass();
}
// Target ~15% of the available heap.
return 1024 * 1024 * memoryClass / 7;
}
public static long calculateDiskCacheSize(File dir, int minSize, int maxSize) {
long size = minSize;
try {
StatFs statFs = new StatFs(dir.getAbsolutePath());
long available = ((long) statFs.getBlockCount()) * statFs.getBlockSize();
// Target 2% of the total space.
size = available / 50;
} catch (IllegalArgumentException ignored) {
}
// Bound inside min/max size for disk cache.
return Math.max(Math.min(size, maxSize), minSize);
}
/**
* returns true if the media is present
* and mounted at its mount point with read/write access.
*
* @return
* @see android.os.Environment#MEDIA_MOUNTED
*/
public static boolean isPrimaryExternalStorageMounted() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
/**
* Use this instead of EnvironmentCompat.
* <p/>
* returns true if the media is present
* and mounted at its mount point with read/write access.
*
* @param path
* @return
* @see android.os.Environment#MEDIA_MOUNTED
*/
public static boolean isSecondaryExternalStorageMounted(File path) {
if (path == null) { // fast precondition
return false;
}
boolean result = false;
if (hasKitKat()) {
result = Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(path));
} else {
try {
String[] l = path.list();
result = l != null && l.length > 0;
} catch (Throwable e) {
LOG.error("Error detecting secondary external storage state", e);
}
}
return result;
}
public static boolean isPrimaryExternalPath(File path) {
String primary = Environment.getExternalStorageDirectory().getAbsolutePath();
return path != null ? path.getAbsolutePath().startsWith(primary) : null;
}
public static long getAvailableStorageSize(File dir) {
long size = -1;
try {
StatFs stat = new StatFs(dir.getAbsolutePath());
size = ((long) stat.getAvailableBlocks()) * stat.getBlockSize();
} catch (Throwable e) {
size = -1; // system error computing the available storage size
}
return size;
}
/**
*
* Use this instead ContextCompat
*
* @param context
* @return
*/
public static File[] getExternalFilesDirs(Context context) {
if (hasKitKat()) {
List<File> dirs = new LinkedList<File>();
for (File f : ContextCompat.getExternalFilesDirs(context, null)) {
if (f != null) {
dirs.add(f);
}
}
return dirs.toArray(new File[0]);
} else {
List<File> dirs = new LinkedList<File>();
dirs.add(context.getExternalFilesDir(null));
try {
String secondaryStorages = System.getenv("SECONDARY_STORAGE");
if (secondaryStorages != null) {
String[] storages = secondaryStorages.split(File.pathSeparator);
for (String s : storages) {
dirs.add(new File(s));
}
}
} catch (Throwable e) {
LOG.error("Unable to get secondary external storages", e);
}
return dirs.toArray(new File[0]);
}
}
public static boolean hasSdk(int versionCode) {
return Build.VERSION.SDK_INT >= versionCode;
}
/**
* Used to determine if the device is running Jelly Bean or greater
*
* @return True if the device is running Jelly Bean or greater, false
* otherwise
*/
public static final boolean hasJellyBean() {
return hasSdk(VERSION_CODE_JELLY_BEAN);
}
/**
* Used to determine if the device is running
* Jelly Bean MR2 (Android 4.3) or greater
*
* @return True if the device is running Jelly Bean MR2 or greater,
* false otherwise
*/
public static final boolean hasJellyBeanMR2() {
return hasSdk(VERSION_CODE_JELLY_BEAN_MR2);
}
/**
* Used to determine if the device is running
* KitKat (Android 4.4) or greater
*
* @return True if the device is running KitKat or greater,
* false otherwise
*/
public static final boolean hasKitKat() {
return hasSdk(VERSION_CODE_KITKAT);
}
}