Returns the children of a {@link FileEntry}.
This method supports a cache mechanism and synchronous and asynchronous modes.
If receiver is null
, the device side ls
command is done synchronously, and the method will return upon completion of the command.
If receiver is non null
, the command is launched is a separate
thread and upon completion, the receiver will be notified of the result.
The result for each ls
command is cached in the parent
FileEntry
. useCache allows usage of this cache, but only if the
cache is valid. The cache is valid only for {@link FileListingService#REFRESH_RATE} ms.
After that a new ls
command is always executed.
If the cache is valid and useCache == true
, the method will always simply
return the value of the cache, whether a {@link IListingReceiver} has been provided or not.
// first thing we do is check the cache, and if we already have a recent
// enough children list, we just return that.
if (useCache && entry.needFetch() == false) {
return entry.getCachedChildren();
}
// if there's no receiver, then this is a synchronous call, and we
// return the result of ls
if (receiver == null) {
doLs(entry);
return entry.getCachedChildren();
}
// this is a asynchronous call.
// we launch a thread that will do ls and give the listing
// to the receiver
Thread t = new Thread("ls " + entry.getFullPath()) { //$NON-NLS-1$
@Override
public void run() {
doLs(entry);
receiver.setChildren(entry, entry.getCachedChildren());
final FileEntry[] children = entry.getCachedChildren();
if (children.length > 0 && children[0].isApplicationPackage()) {
final HashMap<String, FileEntry> map = new HashMap<String, FileEntry>();
for (FileEntry child : children) {
String path = child.getFullPath();
map.put(path, child);
}
// call pm.
String command = PM_FULL_LISTING;
try {
mDevice.executeShellCommand(command, new MultiLineReceiver() {
@Override
public void processNewLines(String[] lines) {
for (String line : lines) {
if (line.length() > 0) {
// get the filepath and package from the line
Matcher m = sPmPattern.matcher(line);
if (m.matches()) {
// get the children with that path
FileEntry entry = map.get(m.group(1));
if (entry != null) {
entry.info = m.group(2);
receiver.refreshEntry(entry);
}
}
}
}
}
public boolean isCancelled() {
return false;
}
});
} catch (IOException e) {
// adb failed somehow, we do nothing.
}
}
// if another thread is pending, launch it
synchronized (mThreadList) {
// first remove ourselves from the list
mThreadList.remove(this);
// then launch the next one if applicable.
if (mThreadList.size() > 0) {
Thread t = mThreadList.get(0);
t.start();
}
}
}
};
// we don't want to run multiple ls on the device at the same time, so we
// store the thread in a list and launch it only if there's no other thread running.
// the thread will launch the next one once it's done.
synchronized (mThreadList) {
// add to the list
mThreadList.add(t);
// if it's the only one, launch it.
if (mThreadList.size() == 1) {
t.start();
}
}
// and we return null.
return null;