summaryrefslogtreecommitdiff
authorTellen Yu <tellen.yu@amlogic.com>2017-10-30 06:28:18 (GMT)
committer Gerrit Code Review <gituser@scgit.amlogic.com>2017-10-30 06:28:18 (GMT)
commit9619e7c53e6837decea8002caf01c59710709dad (patch)
treec0254a102378d88b6726accebbfdf7b23f1fd6f8
parent22517dfe2841decac94db7b389117bbae79c886a (diff)
parent7066f3fc8ad66402d7695fbff027b921a7dd6892 (diff)
downloadframeworks-9619e7c53e6837decea8002caf01c59710709dad.zip
frameworks-9619e7c53e6837decea8002caf01c59710709dad.tar.gz
frameworks-9619e7c53e6837decea8002caf01c59710709dad.tar.bz2
Merge "FileListManager: add FileListManager & droidvold: add droidmount binder service[4/5]" into o-amlogic
Diffstat
-rw-r--r--core/java/com/droidlogic/app/FileListManager.java535
-rw-r--r--core/java/com/droidlogic/app/IDroidVoldManager.java402
-rw-r--r--core/res/src/com/droidlogic/DroidVoldManager.java310
3 files changed, 1246 insertions, 1 deletions
diff --git a/core/java/com/droidlogic/app/FileListManager.java b/core/java/com/droidlogic/app/FileListManager.java
new file mode 100644
index 0000000..bb95408
--- a/dev/null
+++ b/core/java/com/droidlogic/app/FileListManager.java
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * @author XiaoLiang.Wang
+ * @version 1.0
+ * @date 2017/09/20
+ * @par function description:
+ * - 1 get amlogic volume files list
+ */
+
+package com.droidlogic.app;
+
+import android.content.Context;
+import android.util.Log;
+import android.os.Environment;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.os.storage.StorageManager;
+import android.os.storage.DiskInfo;
+import android.os.storage.VolumeInfo;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.lang.String;
+
+import com.droidlogic.app.SystemControlManager;
+import com.droidlogic.app.IDroidVoldManager;
+
+public class FileListManager {
+ private String TAG = "FileListManager";
+ private boolean mDebug = false;
+ private Context mContext;
+
+ private StorageManager mStorageManager;
+ private static SystemControlManager mSystemControl;
+ private IDroidVoldManager mDroidVoldManager;
+
+ public static final String STORAGE = "/storage";
+ public static final String MEDIA_RW = "/mnt/media_rw";
+ public static final String NAND = Environment.getExternalStorageDirectory().getPath();//storage/emulated/0
+
+ private static String ISOpath = null;
+ private static final String iso_mount_dir_s = "/mnt/loop";
+
+ private List<Map<String, Object>> mListDev = new ArrayList<Map<String, Object>>();
+ private List<Map<String, Object>> mListFile = new ArrayList<Map<String, Object>>();
+ private List<Map<String, Object>> mListDir = new ArrayList<Map<String, Object>>();
+ private Map<String, Object> mMap;
+ //key for map
+ public static final String KEY_NAME = "key_name";
+ public static final String KEY_PATH = "key_path";
+ public static final String KEY_TYPE = "key_type";
+ public static final String KEY_DATE = "key_date";
+ public static final String KEY_SIZE = "key_size";
+ public static final String KEY_SELE = "key_sele";
+ public static final String KEY_RDWR = "key_rdwr";
+
+ //type for storage
+ public static final String TYPE_NAND = "type_nand";
+ public static final String TYPE_UDISK = "type_udisk";
+ public static final String TYPE_SDCARD = "type_sdcard";
+
+ //selected flag
+ public static final String SELE_NO = "sele_no";
+ public static final String SELE_YES = "sele_yes";
+
+ /* file type extensions */
+ //video
+ private static final String video_extensions = "3gp,asf,avi,dat,divx,f4v,flv,h264,iso,lst,m2ts,m4v,mkv,mp2,mp4,mov,mpe,mpeg,mpg,mts,rm,rmvb,ts,tp,mvc,vc1,vob,wm,wmv,webm,m2v,pmp,bit,h265,3g2,mlv,hm10,ogm,vp9,trp,bin,ivf";
+
+ //music
+ private static final String[] music_extensions = {
+ ".mp3", ".wma", ".m4a", ".aac", ".ape", ".mp2", ".ogg", ".flac", ".alac", ".wav",
+ ".mid", ".xmf", ".mka", ".aiff", ".aifc", ".aif", ".pcm", ".adpcm"
+ };
+
+ //photo
+ private static final String[] photo_extensions = {
+ ".jpg", ".jpeg", ".bmp", ".tif", ".tiff", ".png", ".gif", ".giff", ".jfi", ".jpe", ".jif",
+ ".jfif", ".mpo", ".webp", ".3dg", "3dp"
+ };
+
+ private static final String[] plain_extensions = {".txt",".c",".cpp",".java",",conf",".h",
+ ".log",".rc"
+ };
+
+ public FileListManager(Context context) {
+ mContext = context;
+ mDebug = false;
+ mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
+ mSystemControl = new SystemControlManager(context);
+ mDroidVoldManager = IDroidVoldManager.Stub.asInterface(ServiceManager.getService("droidmount"));
+
+ checkDebug();
+ }
+
+ private void checkDebug() {
+ if (SystemProperties.getBoolean("sys.filelistanager.debug", false)) {
+ mDebug = true;
+ }
+ }
+
+ public static boolean isVideo(String filename) {
+ String name = filename.toLowerCase();
+ String videos[] = video_extensions.split(",");
+ for (String ext : videos) {
+ if (name.endsWith(ext))
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isMusic(String filename) {
+ String name = filename.toLowerCase();
+ for (String ext : music_extensions) {
+ if (name.endsWith(ext))
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isPhoto(String filename) {
+ String name = filename.toLowerCase();
+ for (String ext : photo_extensions) {
+ if (name.endsWith(ext))
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isApk(String filename) {
+ String name = filename.toLowerCase();
+ if (name.endsWith(".apk"))
+ return true;
+ return false;
+ }
+
+ public static boolean isHtm(String filename) {
+ String name = filename.toLowerCase();
+ if (name.endsWith(".htm") || name.endsWith(".shtml") || name.endsWith(".bin"))
+ return true;
+ return false;
+ }
+
+ public static boolean isPdf(String filename) {
+ String name = filename.toLowerCase();
+ if (name.endsWith(".pdf"))
+ return true;
+ return false;
+ }
+
+ public static boolean isPlain(String filename) {
+ String name = filename.toLowerCase();
+ for (String ext : plain_extensions) {
+ if (name.endsWith(ext))
+ return true;
+ }
+ return false;
+ }
+
+ private static void mount(String path) {
+ mSystemControl.loopMountUnmount(false, null);
+ mSystemControl.loopMountUnmount(true, path);
+ }
+
+ public static boolean isISOFile (File file) {
+ String fname = file.getName();
+ String sname = ".iso";
+ if (fname == "") {
+ return false;
+ }
+ if (file.isFile() && fname.toLowerCase().endsWith (sname)) {
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean isHasDir(File[] files, String name) {
+ for (File file : files) {
+ if (name != null && name.equals(file.getName()) && file.isDirectory())
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isBDFile(File file) {
+ if (file.isDirectory()) {
+ File[] rootFiles = file.listFiles();
+ if (rootFiles != null && rootFiles.length >= 1 && isHasDir(rootFiles, "BDMV")) {
+ File bdDir = new File(file.getPath(), "BDMV");
+ String[] files = bdDir.list();
+ ArrayList<String> names = new ArrayList<String>();
+ for (int i = 0; i < files.length; i++)
+ names.add(files[i]);
+ if (names.contains("index.bdmv") && names.contains("PLAYLIST")
+ && names.contains("CLIPINF") && names.contains("STREAM"))
+ return true;
+ }
+ } else if (isISOFile(file)) {
+ ISOpath = file.getPath();
+ mount(ISOpath);
+ File isofile = new File(iso_mount_dir_s);
+ if (isofile.exists() && isofile.isDirectory()) {
+ File[] rootFiles = isofile.listFiles();
+ if (rootFiles != null && rootFiles.length >= 1 && isHasDir(rootFiles, "BDMV")) {
+ File bdfiles = new File(iso_mount_dir_s, "BDMV");
+ String[] bdmvFiles = bdfiles.list();
+ ArrayList<String> names = new ArrayList<String>();
+ for (int i = 0; i < bdmvFiles.length; i++)
+ names.add(bdmvFiles[i]);
+ if (names.contains("index.bdmv") && names.contains("PLAYLIST")
+ && names.contains("CLIPINF") && names.contains("STREAM")) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public static String CheckMediaType(File file){
+ String typeStr="application/*";
+ String filename = file.getName();
+
+ if (isVideo(filename))
+ typeStr = "video/*";
+ else if (isMusic(filename))
+ typeStr = "audio/*";
+ else if (isPhoto(filename))
+ typeStr = "image/*";
+ else if (isApk(filename))
+ typeStr = "application/vnd.android.package-archive";
+ else if (isHtm(filename))
+ typeStr = "text/html";
+ else if (isPdf(filename))
+ typeStr = "application/pdf";
+ else if (isPlain(filename))
+ typeStr = "text/plain";
+ else {
+ typeStr = "application/*";
+ }
+ return typeStr;
+ }
+
+ public class MyFilter implements FileFilter {
+ private String extensions;
+ public MyFilter (String extensions) {
+ this.extensions = extensions;
+ }
+ public boolean accept (File file) {
+ StringTokenizer st = new StringTokenizer (this.extensions, ",");
+ if (file.isDirectory()) {
+ return true;
+ }
+ String name = file.getName();
+ if (st.countTokens() == 1) {
+ String str = st.nextToken();
+ String filenamelowercase = name.toLowerCase();
+ return filenamelowercase.endsWith (str);
+ } else {
+ int index = name.lastIndexOf (".");
+ if (index == -1) {
+ return false;
+ }
+ else if (index == (name.length() - 1)) {
+ return false;
+ }
+ else {
+ //for(int i = 0; i<st.countTokens(); i++)
+ while (st.hasMoreElements()) {
+ String extension = st.nextToken();
+ if (extension.equals (name.substring (index + 1).toLowerCase())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ }
+ }
+
+ public List<Map<String, Object>> getDevices() {
+ Map<String, Object> map;
+ //local disk (nand)
+ mListDev.clear();
+ File file = new File(NAND);
+ if (file != null && file.exists() && file.isDirectory() && file.listFiles() != null && file.listFiles().length > 0) {
+ map = new HashMap<String, Object>();
+ map.put(KEY_NAME, "Local Disk");
+ map.put(KEY_PATH, NAND);
+ map.put(KEY_DATE, 0);
+ map.put(KEY_SIZE, 1);
+ map.put(KEY_SELE, SELE_NO);
+ map.put(KEY_TYPE, TYPE_NAND);
+ map.put(KEY_RDWR, null);
+
+ if (mDebug) {
+ Log.i(TAG, "[getDevices]nand path:" + NAND);
+ }
+ mListDev.add(map);
+ }
+
+ //external storage
+ Class<?> volumeInfoClazz = null;
+ Method getDescriptionComparator = null;
+ Method getBestVolumeDescription = null;
+ Method getVolumes = null;
+ Method isMountedReadable = null;
+ Method getType = null;
+ Method getPath = null;
+ Method getDisk = null;
+ List<?> volumes = null;
+ try {
+ volumeInfoClazz = Class.forName("android.os.storage.VolumeInfo");
+ getDescriptionComparator = volumeInfoClazz.getMethod("getDescriptionComparator");
+ getBestVolumeDescription = StorageManager.class.getMethod("getBestVolumeDescription", volumeInfoClazz);
+ getVolumes = StorageManager.class.getMethod("getVolumes");
+ isMountedReadable = volumeInfoClazz.getMethod("isMountedReadable");
+ getType = volumeInfoClazz.getMethod("getType");
+ getPath = volumeInfoClazz.getMethod("getPath");
+ getDisk = volumeInfoClazz.getMethod("getDisk");
+ volumes = (List<?>)getVolumes.invoke(mStorageManager);
+ //Collections.sort(volumes, getDescriptionComparator.invoke());
+
+ for (Object vol : volumes) {
+ if (vol != null && (boolean)isMountedReadable.invoke(vol) && (int)getType.invoke(vol) == 0) {
+ File pathFile = (File)getPath.invoke(vol);
+ String path = pathFile.getAbsolutePath();
+ String name = (String)getBestVolumeDescription.invoke(mStorageManager, vol);
+
+ map = new HashMap<String, Object>();
+ map.put(KEY_NAME, name);
+ map.put(KEY_PATH, path);
+ map.put(KEY_DATE, 0);
+ map.put(KEY_SIZE, 1);
+ map.put(KEY_SELE, SELE_NO);
+ map.put(KEY_RDWR, null);
+ DiskInfo disk = (DiskInfo)getDisk.invoke(vol);
+ if (disk.isUsb()) {
+ map.put(KEY_TYPE, TYPE_UDISK);
+ }
+ else {
+ map.put(KEY_TYPE, TYPE_SDCARD);
+ }
+
+ if (mDebug) {
+ Log.i(TAG, "[getDevices]volume path:" + path);
+ }
+ mListDev.add(map);
+ }
+ }
+ } catch (Exception ex) {
+ Log.e(TAG, "[getDevices]Exception ex:" + ex);
+ ex.printStackTrace();
+ }
+
+ //check storage
+ file = new File(STORAGE);
+ if (file != null && file.exists() && file.isDirectory()) {
+ // TODO: needn't check right now
+ }
+
+ //check /mnt/media_rw/
+ file = new File(MEDIA_RW);
+ if (file != null && file.exists() && file.isDirectory()) {
+ Map<String, Object> maptmp;
+ boolean skipFlag = false;
+
+ for (File filetmp : file.listFiles()) {
+ skipFlag = false;
+ String path = filetmp.getAbsolutePath();
+ String name = filetmp.getName();
+ if (mDebug) {
+ Log.i(TAG, "[getDevices]name:" + name + ", path:" + path);
+ }
+ if (mListDev != null && !mListDev.isEmpty()) {
+ for (int i = 0; i < mListDev.size(); i++) {
+ //get uuid to compare with list files' name
+ String uuid = null;
+ maptmp = mListDev.get(i);
+ if (maptmp != null) {
+ String pathtmp = (String) maptmp.get(KEY_PATH);
+ if (pathtmp != null) {
+ int idx = pathtmp.lastIndexOf("/");
+ if (idx >= 0) {
+ uuid = pathtmp.substring(idx + 1);
+ }
+ }
+ }
+
+ if (mDebug) {
+ Log.i(TAG, "[getDevices]uuid:" + uuid);
+ }
+ if (uuid != null && uuid.equals(name)) {
+ skipFlag = true;
+ break;
+ }
+ }
+ }
+
+ if (!skipFlag) {
+ skipFlag = true;//reset skip flag
+ map = new HashMap<String, Object>();
+ map.put(KEY_NAME, name);
+ map.put(KEY_PATH, path);
+ map.put(KEY_DATE, 0);
+ map.put(KEY_SIZE, 1);
+ map.put(KEY_SELE, SELE_NO);
+ map.put(KEY_RDWR, null);
+ int diskFlag = 0;
+ try {
+ diskFlag = mDroidVoldManager.getVolumeInfoDiskFlags(path);
+ } catch (Exception e) {
+ Log.e(TAG, "[getDevices]Exception e:" + e);
+ e.printStackTrace();
+ }
+ Log.i(TAG, "getDevices() diskFlag:" + diskFlag);
+ if (diskFlag == 8) {
+ map.put(KEY_TYPE, TYPE_UDISK);
+ }
+ else if (diskFlag == 4){
+ map.put(KEY_TYPE, TYPE_SDCARD);
+ }
+ if (mDebug) {
+ Log.i(TAG, "[getDevices]/mnt/media_rw path:" + path);
+ }
+ mListDev.add(map);
+ }
+ }
+ }
+
+ if (mDebug) {
+ Log.i(TAG, "[getDevices]====start print list==========================");
+ if (mListDev != null && !mListDev.isEmpty()) {
+ Map<String, Object> maptmp;
+ int listSize = mListDev.size();
+ for (int i = 0; i < listSize; i++) {
+ maptmp = mListDev.get(i);
+ if (maptmp != null) {
+ String nametmp = (String) maptmp.get(KEY_NAME);
+ String pathtmp = (String) maptmp.get(KEY_PATH);
+ }
+ }
+ }
+ Log.i(TAG, "[getDevices]====end print list==========================");
+ }
+
+ return mListDev;
+ }
+
+ public List<Map<String, Object>> getDirs(String directory, String strs) {
+ Map<String, Object> map;
+ String extensions = video_extensions;
+ mListDir.clear();
+ File pfile = new File(directory);
+ File[] files = null;
+ if (strs.indexOf(".") == 0) {
+ files = pfile.listFiles(new MyFilter(strs));
+ } else if (strs.equals("video")) {
+ files = pfile.listFiles(new MyFilter(extensions));
+ }
+ if (files != null && (files.length > 0)) {
+ for (int i = 0; i < files.length; i++) {
+ String pathtmp = files[i].getAbsolutePath();
+ String nametmp = files[i].getName();
+ String str = null;
+ File tempF = files[i];
+ str = files[i].toString();
+ map = new HashMap<String, Object>();
+ map.put(KEY_NAME, nametmp);
+ map.put(KEY_PATH, pathtmp);
+ map.put(KEY_DATE, 0);
+ map.put(KEY_SIZE, 1);
+ map.put(KEY_SELE, SELE_NO);
+ map.put(KEY_RDWR, null);
+ map.put(KEY_TYPE, null);
+ if (mDebug) {
+ Log.i(TAG, "[getDirs]volume pathtmp:" + pathtmp);
+ }
+ if (strs == ".apk") {
+ mListDir.add(map);
+ } else if (strs == "video" && (isBDFile(tempF) || (tempF.isFile() && !isISOFile(tempF)))) {
+ mListDir.add(map);
+ } else if (strs == "video") {
+ mListDir.add(map);
+ }
+ }
+ }
+ return mListDir;
+ }
+
+ public List<Map<String, Object>> getFiles(String path) {
+ Map<String, Object> map;
+ mListFile.clear();
+ File file = new File(path);
+ if (file != null && file.exists() && file.isDirectory()) {
+ for (File filetmp : file.listFiles()) {
+ String pathtmp = filetmp.getAbsolutePath();
+ String nametmp = filetmp.getName();
+ map = new HashMap<String, Object>();
+ map.put(KEY_NAME, nametmp);
+ map.put(KEY_PATH, pathtmp);
+ map.put(KEY_DATE, 0);
+ map.put(KEY_SIZE, 1);
+ map.put(KEY_SELE, SELE_NO);
+ map.put(KEY_RDWR, null);
+ map.put(KEY_TYPE, null);
+ if (mDebug) {
+ Log.i(TAG, "[getFiles]volume pathtmp:" + pathtmp);
+ }
+ mListFile.add(map);
+ }
+ }
+ return mListFile;
+ }
+} \ No newline at end of file
diff --git a/core/java/com/droidlogic/app/IDroidVoldManager.java b/core/java/com/droidlogic/app/IDroidVoldManager.java
new file mode 100644
index 0000000..c98d8a9
--- a/dev/null
+++ b/core/java/com/droidlogic/app/IDroidVoldManager.java
@@ -0,0 +1,402 @@
+package com.droidlogic.app;
+
+public interface IDroidVoldManager extends android.os.IInterface {
+ /** Local-side IPC implementation stub class. */
+ public static abstract class Stub extends android.os.Binder implements com.droidlogic.app.IDroidVoldManager {
+ private static final java.lang.String DESCRIPTOR = "com.droidlogic.app.IDroidVoldManager";
+
+ /** Construct the stub at attach it to the interface. */
+ public Stub() {
+ this.attachInterface(this, DESCRIPTOR);
+ }
+
+ /**
+ * Cast an IBinder object into an com.droidlogic.app.IDroidVoldManager interface,
+ * generating a proxy if needed.
+ */
+
+ public static com.droidlogic.app.IDroidVoldManager asInterface(android.os.IBinder obj) {
+ if ((obj == null)) {
+ return null;
+ }
+
+ android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+ if (((iin != null) && (iin instanceof com.droidlogic.app.IDroidVoldManager))) {
+ return ((com.droidlogic.app.IDroidVoldManager)iin);
+ }
+ return new com.droidlogic.app.IDroidVoldManager.Stub.Proxy(obj);
+ }
+
+ @Override
+ public android.os.IBinder asBinder() {
+ return this;
+ }
+
+ @Override
+ public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
+ throws android.os.RemoteException {
+ switch (code) {
+ case INTERFACE_TRANSACTION: {
+ reply.writeString(DESCRIPTOR);
+ return true;
+ }
+
+ case TRANSACTION_formatVolume: {
+ data.enforceInterface(DESCRIPTOR);
+ java.lang.String _arg0;
+ _arg0 = data.readString();
+
+ int _result = this.formatVolume(_arg0);
+ reply.writeNoException();
+ reply.writeInt(_result);
+ return true;
+ }
+
+ case TRANSACTION_shutdown: {
+ data.enforceInterface(DESCRIPTOR);
+ android.os.storage.IStorageShutdownObserver _arg0;
+ _arg0 = android.os.storage.IStorageShutdownObserver.Stub.asInterface(data.readStrongBinder());
+ this.shutdown(_arg0);
+ reply.writeNoException();
+ return true;
+ }
+
+ case TRANSACTION_getVolumeList: {
+ data.enforceInterface(DESCRIPTOR);
+ int _arg0;
+ _arg0 = data.readInt();
+ java.lang.String _arg1;
+ _arg1 = data.readString();
+ int _arg2;
+ _arg2 = data.readInt();
+ android.os.storage.StorageVolume[] _result = this.getVolumeList(_arg0, _arg1, _arg2);
+ reply.writeNoException();
+ reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ return true;
+ }
+
+ case TRANSACTION_mkdirs: {
+ data.enforceInterface(DESCRIPTOR);
+ java.lang.String _arg0;
+ _arg0 = data.readString();
+ java.lang.String _arg1;
+ _arg1 = data.readString();
+ int _result = this.mkdirs(_arg0, _arg1);
+ reply.writeNoException();
+ reply.writeInt(_result);
+ return true;
+ }
+
+ case TRANSACTION_getDisks: {
+ data.enforceInterface(DESCRIPTOR);
+ android.os.storage.DiskInfo[] _result = this.getDisks();
+ reply.writeNoException();
+ reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ return true;
+ }
+
+
+ case TRANSACTION_getVolumes: {
+ data.enforceInterface(DESCRIPTOR);
+ int _arg0;
+ _arg0 = data.readInt();
+ android.os.storage.VolumeInfo[] _result = this.getVolumes(_arg0);
+ reply.writeNoException();
+ reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ return true;
+ }
+
+
+ case TRANSACTION_getVolumeRecords: {
+ data.enforceInterface(DESCRIPTOR);
+ int _arg0;
+ _arg0 = data.readInt();
+ android.os.storage.VolumeRecord[] _result = this.getVolumeRecords(_arg0);
+ reply.writeNoException();
+ reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ return true;
+ }
+
+ case TRANSACTION_mount: {
+ data.enforceInterface(DESCRIPTOR);
+ java.lang.String _arg0;
+ _arg0 = data.readString();
+ this.mount(_arg0);
+ reply.writeNoException();
+ return true;
+ }
+
+ case TRANSACTION_unmount: {
+ data.enforceInterface(DESCRIPTOR);
+ java.lang.String _arg0;
+ _arg0 = data.readString();
+ this.unmount(_arg0);
+ reply.writeNoException();
+ return true;
+ }
+
+ case TRANSACTION_format: {
+ data.enforceInterface(DESCRIPTOR);
+ java.lang.String _arg0;
+ _arg0 = data.readString();
+ this.format(_arg0);
+ reply.writeNoException();
+ return true;
+ }
+
+ case TRANSACTION_getVolumeInfoDiskFlags: {
+ data.enforceInterface(DESCRIPTOR);
+ java.lang.String _arg0;
+ _arg0 = data.readString();
+ int _result = this.getVolumeInfoDiskFlags(_arg0);
+ reply.writeNoException();
+ reply.writeInt(_result);
+ return true;
+ }
+ }
+
+ return super.onTransact(code, data, reply, flags);
+ }
+
+ private static class Proxy implements com.droidlogic.app.IDroidVoldManager {
+ private android.os.IBinder mRemote;
+
+ Proxy(android.os.IBinder remote) {
+ mRemote = remote;
+ }
+
+ @Override
+ public android.os.IBinder asBinder() {
+ return mRemote;
+ }
+
+ public java.lang.String getInterfaceDescriptor() {
+ return DESCRIPTOR;
+ }
+
+ @Override
+ public int formatVolume(java.lang.String mountPoint) throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ int _result;
+
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(mountPoint);
+ mRemote.transact(Stub.TRANSACTION_formatVolume, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+
+ return _result;
+ }
+
+ @Override
+ public void shutdown(android.os.storage.IStorageShutdownObserver observer) throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeStrongBinder((((observer!=null))?(observer.asBinder()):(null)));
+ mRemote.transact(Stub.TRANSACTION_shutdown, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+
+ @Override
+ public android.os.storage.StorageVolume[] getVolumeList(int uid, java.lang.String packageName, int flags)
+ throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ android.os.storage.StorageVolume[] _result;
+
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(uid);
+ _data.writeString(packageName);
+ _data.writeInt(flags);
+ mRemote.transact(Stub.TRANSACTION_getVolumeList, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.createTypedArray(android.os.storage.StorageVolume.CREATOR);
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+
+ return _result;
+ }
+
+ @Override
+ public int mkdirs(java.lang.String callingPkg, java.lang.String path) throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ int _result;
+
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(callingPkg);
+ _data.writeString(path);
+ mRemote.transact(Stub.TRANSACTION_mkdirs, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+
+ return _result;
+ }
+
+ @Override
+ public android.os.storage.DiskInfo[] getDisks() throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ android.os.storage.DiskInfo[] _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ mRemote.transact(Stub.TRANSACTION_getDisks, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.createTypedArray(android.os.storage.DiskInfo.CREATOR);
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+
+ return _result;
+ }
+
+ @Override
+ public android.os.storage.VolumeInfo[] getVolumes(int flags) throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ android.os.storage.VolumeInfo[] _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(flags);
+ mRemote.transact(Stub.TRANSACTION_getVolumes, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.createTypedArray(android.os.storage.VolumeInfo.CREATOR);
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+
+ return _result;
+ }
+
+ @Override
+ public android.os.storage.VolumeRecord[] getVolumeRecords(int flags) throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ android.os.storage.VolumeRecord[] _result;
+
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(flags);
+ mRemote.transact(Stub.TRANSACTION_getVolumeRecords, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.createTypedArray(android.os.storage.VolumeRecord.CREATOR);
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+
+ return _result;
+ }
+
+ @Override
+ public void mount(java.lang.String volId) throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(volId);
+ mRemote.transact(Stub.TRANSACTION_mount, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ @Override
+ public void unmount(java.lang.String volId) throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(volId);
+ mRemote.transact(Stub.TRANSACTION_unmount, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ @Override
+ public void format(java.lang.String volId) throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(volId);
+ mRemote.transact(Stub.TRANSACTION_format, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+ @Override public int getVolumeInfoDiskFlags(java.lang.String mountPoint) throws android.os.RemoteException {
+ android.os.Parcel _data = android.os.Parcel.obtain();
+ android.os.Parcel _reply = android.os.Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(mountPoint);
+ mRemote.transact(Stub.TRANSACTION_getVolumeInfoDiskFlags, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ }
+ finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+ }
+
+ static final int TRANSACTION_formatVolume = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+ static final int TRANSACTION_shutdown = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+ static final int TRANSACTION_getVolumeList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
+ static final int TRANSACTION_mkdirs = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
+ static final int TRANSACTION_getDisks = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
+ static final int TRANSACTION_getVolumes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
+ static final int TRANSACTION_getVolumeRecords = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
+ static final int TRANSACTION_mount = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
+ static final int TRANSACTION_unmount = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
+ static final int TRANSACTION_format = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);
+ static final int TRANSACTION_getVolumeInfoDiskFlags = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10);
+ }
+
+ public int formatVolume(java.lang.String mountPoint) throws android.os.RemoteException;
+ public void shutdown(android.os.storage.IStorageShutdownObserver observer) throws android.os.RemoteException;
+ public android.os.storage.StorageVolume[] getVolumeList(int uid, java.lang.String packageName, int flags) throws android.os.RemoteException;
+ public int mkdirs(java.lang.String callingPkg, java.lang.String path) throws android.os.RemoteException;
+ public android.os.storage.DiskInfo[] getDisks() throws android.os.RemoteException;
+ public android.os.storage.VolumeInfo[] getVolumes(int flags) throws android.os.RemoteException;
+ public android.os.storage.VolumeRecord[] getVolumeRecords(int flags) throws android.os.RemoteException;
+ public void mount(java.lang.String volId) throws android.os.RemoteException;
+ public void unmount(java.lang.String volId) throws android.os.RemoteException;
+ public void format(java.lang.String volId) throws android.os.RemoteException;
+ public int getVolumeInfoDiskFlags(java.lang.String mountPoint) throws android.os.RemoteException;
+}
diff --git a/core/res/src/com/droidlogic/DroidVoldManager.java b/core/res/src/com/droidlogic/DroidVoldManager.java
index 018901d..9463838 100644
--- a/core/res/src/com/droidlogic/DroidVoldManager.java
+++ b/core/res/src/com/droidlogic/DroidVoldManager.java
@@ -45,11 +45,13 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.DiskInfo;
import android.os.storage.IStorageShutdownObserver;
import android.os.storage.StorageResultCode;
+import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
@@ -76,6 +78,13 @@ import com.android.internal.widget.LockPatternUtils;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -95,11 +104,14 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import com.droidlogic.app.IDroidVoldManager;
+
/**
* Service responsible for various storage media. Connects to {@code droidvold} to
* watch for and manage dynamically added storage, such as SD cards and USB mass storage.
*/
-class DroidVoldManager implements INativeDaemonConnectorCallbacks {
+class DroidVoldManager extends IDroidVoldManager.Stub
+ implements INativeDaemonConnectorCallbacks {
// Static direct instance pointer for the tightly-coupled idle service to use
static DroidVoldManager sSelf = null;
@@ -629,17 +641,313 @@ class DroidVoldManager implements INativeDaemonConnectorCallbacks {
mConnectorThread = new Thread(mConnector, VOLD_TAG);
Slog.d(TAG, "start nativeNaemon");
mConnectorThread.start();
+ ServiceManager.addService("droidmount", sSelf, false);
+ }
+ private String findVolumeIdForPathOrThrow(String path) {
+ synchronized (mLock) {
+ for (int i = 0; i < mVolumes.size(); i++) {
+ final VolumeInfo vol = mVolumes.valueAt(i);
+ if (vol.path != null && path.startsWith(vol.path)) {
+ return vol.id;
+ }
+ }
+ }
+ throw new IllegalArgumentException("No volume found for path " + path);
+ }
+
+ private VolumeInfo findVolumeByIdOrThrow(String id) {
+ synchronized (mLock) {
+ final VolumeInfo vol = mVolumes.get(id);
+ if (vol != null) {
+ return vol;
+ }
+ }
+ throw new IllegalArgumentException("No volume found for ID " + id);
}
/**
* Exposed API calls below here
*/
+ @Override
public void shutdown(final IStorageShutdownObserver observer) {
enforcePermission(android.Manifest.permission.SHUTDOWN);
Slog.i(TAG, "Shutting down");
mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
}
+
+ @Override
+ public int formatVolume(String path) {
+ format(findVolumeIdForPathOrThrow(path));
+ return 0;
+ }
+
+ @Override
+ public int mkdirs(String callingPkg, String appPath) {
+ final int userId = UserHandle.getUserId(Binder.getCallingUid());
+ final UserEnvironment userEnv = new UserEnvironment(userId);
+
+ File appFile = null;
+ try {
+ appFile = new File(appPath).getCanonicalFile();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to resolve " + appPath + ": " + e);
+ return -1;
+ }
+
+ // Try translating the app path into a vold path, but require that it
+ // belong to the calling package.
+ if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
+ FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
+ FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
+ appPath = appFile.getAbsolutePath();
+ if (!appPath.endsWith("/")) {
+ appPath = appPath + "/";
+ }
+
+ try {
+ mConnector.execute("volume", "mkdirs", appPath);
+ return 0;
+ } catch (NativeDaemonConnectorException e) {
+ return e.getCode();
+ }
+ }
+
+ throw new SecurityException("Invalid mkdirs path: " + appFile);
+ }
+
+ @Override
+ public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
+ final int userId = UserHandle.getUserId(uid);
+
+ final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
+ final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
+ final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
+
+
+ boolean foundPrimary = false;
+
+ final ArrayList<StorageVolume> res = new ArrayList<>();
+ synchronized (mLock) {
+ for (int i = 0; i < mVolumes.size(); i++) {
+ final VolumeInfo vol = mVolumes.valueAt(i);
+ switch (vol.getType()) {
+ case VolumeInfo.TYPE_PUBLIC:
+ case VolumeInfo.TYPE_EMULATED:
+ break;
+ default:
+ continue;
+ }
+
+ boolean match = false;
+ if (forWrite) {
+ match = vol.isVisibleForWrite(userId);
+ } else {
+ match = vol.isVisibleForRead(userId)
+ || (includeInvisible && vol.getPath() != null);
+ }
+ if (!match) continue;
+
+ boolean reportUnmounted = false;
+ if ((vol.getType() == VolumeInfo.TYPE_EMULATED)) {
+ reportUnmounted = true;
+ } else if (!realState) {
+ reportUnmounted = true;
+ }
+
+ final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
+ reportUnmounted);
+ if (vol.isPrimary()) {
+ res.add(0, userVol);
+ foundPrimary = true;
+ } else {
+ res.add(userVol);
+ }
+ }
+ }
+
+ if (!foundPrimary) {
+ Log.w(TAG, "No primary storage defined yet; hacking together a stub");
+
+ final boolean primaryPhysical = SystemProperties.getBoolean(
+ StorageManager.PROP_PRIMARY_PHYSICAL, false);
+
+ final String id = "stub_primary";
+ final File path = Environment.getLegacyExternalStorageDirectory();
+ final String description = mContext.getString(android.R.string.unknownName);
+ final boolean primary = true;
+ final boolean removable = primaryPhysical;
+ final boolean emulated = !primaryPhysical;
+ final long mtpReserveSize = 0L;
+ final boolean allowMassStorage = false;
+ final long maxFileSize = 0L;
+ final UserHandle owner = new UserHandle(userId);
+ final String uuid = null;
+ final String state = Environment.MEDIA_REMOVED;
+
+ res.add(0, new StorageVolume(id, StorageVolume.STORAGE_ID_INVALID, path,
+ description, primary, removable, emulated, mtpReserveSize,
+ allowMassStorage, maxFileSize, owner, uuid, state));
+ }
+
+ return res.toArray(new StorageVolume[res.size()]);
+ }
+
+ @Override
+ public DiskInfo[] getDisks() {
+ synchronized (mLock) {
+ final DiskInfo[] res = new DiskInfo[mDisks.size()];
+ for (int i = 0; i < mDisks.size(); i++) {
+ res[i] = mDisks.valueAt(i);
+ }
+ return res;
+ }
+ }
+
+ @Override
+ public VolumeInfo[] getVolumes(int flags) {
+ synchronized (mLock) {
+ final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
+ for (int i = 0; i < mVolumes.size(); i++) {
+ res[i] = mVolumes.valueAt(i);
+ }
+ return res;
+ }
+ }
+
+ @Override
+ public VolumeRecord[] getVolumeRecords(int flags) {
+ synchronized (mLock) {
+ final VolumeRecord[] res = new VolumeRecord[mRecords.size()];
+ for (int i = 0; i < mRecords.size(); i++) {
+ res[i] = mRecords.valueAt(i);
+ }
+ return res;
+ }
+ }
+
+ @Override
+ public void mount(String volId) {
+ enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
+ waitForReady();
+
+ final VolumeInfo vol = findVolumeByIdOrThrow(volId);
+ if (isMountDisallowed(vol)) {
+ throw new SecurityException("Mounting " + volId + " restricted by policy");
+ }
+ try {
+ mConnector.execute("volume", "mount", vol.id, vol.mountFlags, vol.mountUserId);
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
+ }
+
+ @Override
+ public void unmount(String volId) {
+ enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
+ waitForReady();
+
+ final VolumeInfo vol = findVolumeByIdOrThrow(volId);
+
+ try {
+ mConnector.execute("volume", "unmount", vol.id);
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
+ }
+
+ @Override
+ public void format(String volId) {
+ enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
+ waitForReady();
+
+ final VolumeInfo vol = findVolumeByIdOrThrow(volId);
+ try {
+ mConnector.execute("volume", "format", vol.id, "auto");
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
+ }
+
+ @Override
+ public int getVolumeInfoDiskFlags(String mountPoint) {
+ int flag = 0;
+ int FLAG_SD = 1 << 2;
+ int FLAG_USB = 1 << 3;
+
+ synchronized (mLock) {
+ for (int i = 0; i < mVolumes.size(); i++) {
+ final VolumeInfo vol = mVolumes.valueAt(i);
+ if (vol.path != null && mountPoint.startsWith(vol.path)) {
+ if (vol.getDisk().isSd())
+ flag |= FLAG_SD;
+ else if (vol.getDisk().isUsb())
+ flag |= FLAG_USB;
+ break;
+ }
+ }
+ }
+
+ return flag;
+ }
+
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
+
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ", 160);
+ synchronized (mLock) {
+ pw.println("Disks:");
+ pw.increaseIndent();
+ for (int i = 0; i < mDisks.size(); i++) {
+ final DiskInfo disk = mDisks.valueAt(i);
+ disk.dump(pw);
+ }
+ pw.decreaseIndent();
+
+ pw.println();
+ pw.println("Volumes:");
+ pw.increaseIndent();
+ for (int i = 0; i < mVolumes.size(); i++) {
+ final VolumeInfo vol = mVolumes.valueAt(i);
+ if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) continue;
+ vol.dump(pw);
+ }
+ pw.decreaseIndent();
+
+ pw.println();
+ pw.println("Records:");
+ pw.increaseIndent();
+ for (int i = 0; i < mRecords.size(); i++) {
+ final VolumeRecord note = mRecords.valueAt(i);
+ note.dump(pw);
+ }
+ pw.decreaseIndent();
+
+ final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
+ if (pair == null) {
+ pw.println("Internal storage total size: N/A");
+ } else {
+ pw.print("Internal storage (");
+ pw.print(pair.first);
+ pw.print(") total size: ");
+ pw.print(pair.second);
+ pw.print(" (");
+ pw.print((float) pair.second / TrafficStats.GB_IN_BYTES);
+ pw.println(" GB)");
+ }
+ pw.println();
+ pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
+ }
+
+
+ pw.println();
+ pw.println("mConnector:");
+ pw.increaseIndent();
+ mConnector.dump(fd, pw, args);
+ pw.decreaseIndent();
+ }
}