/* * Copyright 2014 ParanoidAndroid Project * Modifications Copyright (C) 2014 Alexander "Evisceration" Martinz * * This file is part of Paranoid OTA. * * Paranoid OTA 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. * * Paranoid OTA 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 Paranoid OTA. If not, see <http://www.gnu.org/licenses/>. */ package org.namelessrom.devicecontrol.utils; import android.annotation.SuppressLint; import android.os.Build; import android.os.Environment; import android.os.StatFs; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import java.io.File; import java.util.ArrayList; import at.amartinz.execution.RootShell; public class IOUtils { public static final String SDCARD = Environment.getExternalStorageDirectory().getAbsolutePath(); private static IOUtils sInstance; private static boolean sSdcardsChecked; private String sPrimarySdcard; private String sSecondarySdcard; private IOUtils() { readMounts(); } public static IOUtils get() { if (sInstance == null) { sInstance = new IOUtils(); } return sInstance; } public boolean isExternalStorageAvailable() { return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); } @NonNull public String getPrimarySdCard() { return sPrimarySdcard; } @Nullable public String getSecondarySdCard() { return sSecondarySdcard; } @SuppressLint("SdCardPath") private void readMounts() { if (sSdcardsChecked) { return; } ArrayList<String> mounts = new ArrayList<>(); ArrayList<String> vold = new ArrayList<>(); String result = RootShell.fireAndBlockString("cat /proc/mounts;"); String[] output = ((result != null) ? result.split("\n") : new String[0]); for (final String s : output) { if (s.startsWith("/dev/block/vold/")) { String[] lineElements = s.split(" "); if (lineElements[1] == null) { continue; } String element = lineElements[1]; mounts.add(element); } } boolean addExternal = mounts.size() == 1 && isExternalStorageAvailable(); if (mounts.size() == 0 && addExternal) { mounts.add("/mnt/sdcard"); } final File fstab = findFstab(); if (fstab != null) { result = RootShell.fireAndBlockString(String.format("cat %s;", fstab.getAbsolutePath())); output = ((result != null) ? result.split("\n") : new String[0]); for (final String s : output) { //noinspection StatementWithEmptyBody if (TextUtils.isEmpty(s) || s.startsWith("#")) { // do nothing } else if (s.startsWith("dev_mount")) { String[] lineElements = s.split(" "); if (lineElements.length < 3) { continue; } String element = lineElements[2]; if (element == null) { continue; } if (element.contains(":")) { element = element.substring(0, element.indexOf(":")); } if (!element.toLowerCase().contains("usb")) { vold.add(element); } } else if (s.startsWith("/devices/platform")) { String[] lineElements = s.split(" "); if (lineElements.length < 2) { continue; } String element = lineElements[1]; if (element == null) { continue; } if (element.contains(":")) { element = element.substring(0, element.indexOf(":")); } if (!element.toLowerCase().contains("usb")) { vold.add(element); } } } } if (addExternal && (vold.size() == 1 && isExternalStorageAvailable())) { mounts.add(vold.get(0)); } if (vold.size() == 0 && isExternalStorageAvailable()) { vold.add("/mnt/sdcard"); } for (int i = 0; i < mounts.size(); i++) { String mount = mounts.get(i); File root = new File(mount); if (!vold.contains(mount) || (!root.exists() || !root.isDirectory() || !root.canWrite())) { mounts.remove(i--); } } for (final String mount : mounts) { if (!mount.contains("sdcard0") && !mount.equalsIgnoreCase("/mnt/sdcard") && !mount.equalsIgnoreCase("/sdcard")) { sSecondarySdcard = mount; } else { sPrimarySdcard = mount; } } if (sPrimarySdcard == null) { sPrimarySdcard = "/sdcard"; } sSdcardsChecked = true; } private File findFstab() { File file = new File("/system/etc/vold.fstab"); if (file.exists()) { return file; } String fstab = RootShell.fireAndBlockString("grep -ls \"/dev/block/\" * --include=fstab.* --exclude=fstab.goldfish"); if (!TextUtils.isEmpty(fstab)) { final String[] files = fstab.split("\n"); for (final String s : files) { file = new File(s); if (file.exists()) { return file; } } } return null; } public double getSpaceLeft() { final StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath()); final double sdAvailSize; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { sdAvailSize = (double) stat.getAvailableBlocksLong() * (double) stat.getBlockSizeLong(); } else { //noinspection deprecation sdAvailSize = (double) stat.getAvailableBlocks() * (double) stat.getBlockSize(); } // One binary gigabyte equals 1,073,741,824 bytes. return sdAvailSize / 1073741824; } public boolean hasAndroidSecure() { return folderExists(SDCARD + "/.android-secure"); } public boolean hasSdExt() { return folderExists("/sd-ext"); } public boolean folderExists(String path) { File f = new File(path); return f.exists() && f.isDirectory(); } }