summaryrefslogtreecommitdiff
authorBaocheng Sun <baocheng.sun@amlogic.com>2017-10-20 07:08:32 (GMT)
committer Baocheng Sun <baocheng.sun@amlogic.com>2017-10-31 08:27:42 (GMT)
commitaf58a906e0f479a81a798103aaf54a174a183936 (patch)
treeaeb01b6c2b40df99d88de3e9150957a0ea2ced59
parent435ff173bd08cfe9939b4b044ad646d6d075855e (diff)
downloadframeworks-af58a906e0f479a81a798103aaf54a174a183936.zip
frameworks-af58a906e0f479a81a798103aaf54a174a183936.tar.gz
frameworks-af58a906e0f479a81a798103aaf54a174a183936.tar.bz2
DroidVoldManager: use droidvold hwbinder service [3/4]
PD# 151674 communited with droidvold use hwbinder instead of socket Change-Id: I7a19a5b9a736636ac6e9ea5a490b4ee8d6f9eb27
Diffstat
-rw-r--r--core/res/Android.mk7
-rw-r--r--core/res/src/com/droidlogic/DroidVoldManager.java395
-rw-r--r--core/res/src/com/droidlogic/INativeDaemonConnectorCallbacks.java24
-rw-r--r--core/res/src/com/droidlogic/NativeDaemonConnector.java701
-rw-r--r--core/res/src/com/droidlogic/NativeDaemonConnectorException.java58
-rw-r--r--core/res/src/com/droidlogic/NativeDaemonEvent.java268
-rw-r--r--core/res/src/com/droidlogic/NativeDaemonTimeoutException.java28
7 files changed, 212 insertions, 1269 deletions
diff --git a/core/res/Android.mk b/core/res/Android.mk
index 3f8bdd1..2e6c493 100644
--- a/core/res/Android.mk
+++ b/core/res/Android.mk
@@ -3,7 +3,12 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_JAVA_LIBRARIES := droidlogic droidlogic.external.pppoe
+LOCAL_JAVA_LIBRARIES := droidlogic droidlogic.external.pppoe \
+ android.hidl.manager-V1.0-java
+
+LOCAL_STATIC_JAVA_LIBRARIES := android.hidl.base-V1.0-java-static \
+ vendor.amlogic.hardware.droidvold-V1.0-java
+
#LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := droidlogic-res
diff --git a/core/res/src/com/droidlogic/DroidVoldManager.java b/core/res/src/com/droidlogic/DroidVoldManager.java
index 9463838..52dda7b 100644
--- a/core/res/src/com/droidlogic/DroidVoldManager.java
+++ b/core/res/src/com/droidlogic/DroidVoldManager.java
@@ -37,15 +37,14 @@ import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.ServiceManager;
import android.os.Looper;
import android.os.Message;
-import android.os.PowerManager;
-import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.ServiceManager;
+import android.os.StrictMode;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.DiskInfo;
@@ -54,6 +53,7 @@ import android.os.storage.StorageResultCode;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
+import android.os.storage.StorageManager;
import android.os.storage.VolumeRecord;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -66,14 +66,8 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.os.SomeArgs;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
-import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
-import com.android.internal.widget.LockPatternUtils;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
@@ -87,6 +81,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -98,11 +93,20 @@ import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
+
+import vendor.amlogic.hardware.droidvold.V1_0.IDroidVold;
+import vendor.amlogic.hardware.droidvold.V1_0.IDroidVoldCallback;
+import vendor.amlogic.hardware.droidvold.V1_0.Result;
+
+import android.hidl.manager.V1_0.IServiceManager;
+import android.hidl.manager.V1_0.IServiceNotification;
+import android.os.Bundle;
+import android.os.HwBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import java.util.NoSuchElementException;
+
+import com.droidlogic.app.IDroidVoldManager;
import com.droidlogic.app.IDroidVoldManager;
@@ -110,17 +114,13 @@ 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 extends IDroidVoldManager.Stub
- implements INativeDaemonConnectorCallbacks {
-
+class DroidVoldManager extends IDroidVoldManager.Stub {
// Static direct instance pointer for the tightly-coupled idle service to use
static DroidVoldManager sSelf = null;
private static final boolean DEBUG = false;
private static final String TAG = "DroidVoldManager";
- private static final String VOLD_TAG = "DroidVoldConnector";
- private static final int MAX_CONTAINERS = 250;
private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>();
@@ -196,10 +196,6 @@ class DroidVoldManager extends IDroidVoldManager.Stub
*/
private final Object mLock = new Object();
- /** Set of users that system knows are unlocked. */
- @GuardedBy("mLock")
- private int[] mSystemUnlockedUsers = EmptyArray.INT;
-
/** Map from disk ID to disk */
@GuardedBy("mLock")
private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
@@ -215,27 +211,21 @@ class DroidVoldManager extends IDroidVoldManager.Stub
private final Context mContext;
- private final NativeDaemonConnector mConnector;
-
- private final Thread mConnectorThread;
+ private IDroidVold mDroidVold;
- private volatile boolean mDaemonConnected = false;
-
- // Two connectors - mConnector & mCryptConnector
- private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
+ private DroidVoldCallback mDroidVoldCallback;
public static @Nullable String getBroadcastForEnvironment(String envState) {
return sEnvironmentToBroadcast.get(envState);
}
// Handler messages
- private static final int H_DAEMON_CONNECTED = 1;
- private static final int H_SHUTDOWN = 2;
- private static final int H_VOLUME_MOUNT = 3;
- private static final int H_VOLUME_BROADCAST = 4;
- private static final int H_INTERNAL_BROADCAST = 5;
- private static final int H_PARTITION_FORGET = 6;
- private static final int H_RESET = 7;
+ private static final int H_SHUTDOWN = 1;
+ private static final int H_VOLUME_MOUNT = 2;
+ private static final int H_VOLUME_BROADCAST = 3;
+ private static final int H_INTERNAL_BROADCAST = 4;
+ private static final int H_PARTITION_FORGET = 5;
+ private static final int H_RESET = 6;
class DroidVoldManagerHandler extends Handler {
public DroidVoldManagerHandler(Looper looper) {
@@ -245,17 +235,19 @@ class DroidVoldManager extends IDroidVoldManager.Stub
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case H_DAEMON_CONNECTED: {
- handleDaemonConnected();
- break;
- }
case H_SHUTDOWN: {
final IStorageShutdownObserver obs = (IStorageShutdownObserver) msg.obj;
boolean success = false;
try {
- success = mConnector.execute("volume", "shutdown").isClassOk();
- } catch (NativeDaemonConnectorException ignored) {
+ int rs = mDroidVold.shutdown();
+ success = (rs == 0 ? true : false);
+ } catch (NoSuchElementException e) {
+ Slog.e(TAG, "connectToProxy: droidvold hal service not found."
+ + " Did the service fail to start?", e);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "connectToProxy: droidvold hal service not responding", e);
}
+
if (obs != null) {
try {
obs.onShutDownComplete(success ? 0 : -1);
@@ -271,9 +263,9 @@ class DroidVoldManager extends IDroidVoldManager.Stub
break;
}
try {
- mConnector.execute("volume", "mount", vol.id, vol.mountFlags,
- vol.mountUserId);
- } catch (NativeDaemonConnectorException ignored) {
+ mDroidVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "connectToProxy: droidvold hal service not responding", e);
}
break;
}
@@ -284,6 +276,11 @@ class DroidVoldManager extends IDroidVoldManager.Stub
+ userVol.getOwner());
final String action = getBroadcastForEnvironment(envState);
+
+ StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
+ StrictMode.setVmPolicy(builder.build());
+ //builder.detectFileUriExposure();
+
if (action != null) {
final Intent intent = new Intent(action,
Uri.fromFile(userVol.getPathFile()));
@@ -313,94 +310,117 @@ class DroidVoldManager extends IDroidVoldManager.Stub
private final Handler mHandler;
- private void waitForReady() {
- waitForLatch(mConnectedSignal, "mConnectedSignal");
- }
+ private void resetIfReadyAndConnected() {
+ final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
+
+ synchronized (mLock) {
+ mDisks.clear();
+ mVolumes.clear();
+ }
- private void waitForLatch(CountDownLatch latch, String condition) {
try {
- waitForLatch(latch, condition, -1);
- } catch (TimeoutException ignored) {
+ mDroidVold.reset();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "connectToProxy: droidvold hal service not responding", e);
}
}
- private void waitForLatch(CountDownLatch latch, String condition, long timeoutMillis)
- throws TimeoutException {
- final long startMillis = SystemClock.elapsedRealtime();
- while (true) {
- try {
- if (latch.await(5000, TimeUnit.MILLISECONDS)) {
- return;
- } else {
- Slog.w(TAG, "Thread " + Thread.currentThread().getName()
- + " still waiting for " + condition + "...");
- }
- } catch (InterruptedException e) {
- Slog.w(TAG, "Interrupt while waiting for " + condition);
- }
- if (timeoutMillis > 0 && SystemClock.elapsedRealtime() > startMillis + timeoutMillis) {
- throw new TimeoutException("Thread " + Thread.currentThread().getName()
- + " gave up waiting for " + condition + " after " + timeoutMillis + "ms");
- }
+ final class DeathRecipient implements HwBinder.DeathRecipient {
+ @Override
+ public void serviceDied(long cookie) {
+ Slog.d(TAG, "droidvold server died");
}
}
- private void resetIfReadyAndConnected() {
- Slog.d(TAG, "Thinking about reset mDaemonConnected=" + mDaemonConnected);
- if (mDaemonConnected) {
- final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
-
- final int[] systemUnlockedUsers;
- synchronized (mLock) {
- systemUnlockedUsers = mSystemUnlockedUsers;
+ static class DroidVoldCallback extends IDroidVoldCallback.Stub {
+ public DroidVoldManager mDroidVoldManager;
+ // implement methods
+ DroidVoldCallback() {
+ super();
+ }
- mDisks.clear();
- mVolumes.clear();
- }
+ DroidVoldCallback(DroidVoldManager dm) {
+ this.mDroidVoldManager = dm;
+ }
- try {
- mConnector.execute("volume", "reset");
- } catch (NativeDaemonConnectorException e) {
- Slog.w(TAG, "Failed to reset vold", e);
+ public static String[] unescapeArgs(String rawEvent) {
+ final boolean DEBUG_ROUTINE = false;
+ final String LOGTAG = "unescapeArgs";
+ final ArrayList<String> parsed = new ArrayList<String>();
+ final int length = rawEvent.length();
+ int current = 0;
+ int wordEnd = -1;
+ boolean quoted = false;
+
+ if (DEBUG_ROUTINE) Slog.e(LOGTAG, "parsing '" + rawEvent + "'");
+ if (rawEvent.charAt(current) == '\"') {
+ quoted = true;
+ current++;
+ }
+ while (current < length) {
+ // find the end of the word
+ char terminator = quoted ? '\"' : ' ';
+ wordEnd = current;
+ while (wordEnd < length && rawEvent.charAt(wordEnd) != terminator) {
+ if (rawEvent.charAt(wordEnd) == '\\') {
+ // skip the escaped char
+ ++wordEnd;
+ }
+ ++wordEnd;
+ }
+ if (wordEnd > length) wordEnd = length;
+ String word = rawEvent.substring(current, wordEnd);
+ current += word.length();
+ if (!quoted) {
+ word = word.trim();
+ } else {
+ current++; // skip the trailing quote
+ }
+ // unescape stuff within the word
+ word = word.replace("\\\\", "\\");
+ word = word.replace("\\\"", "\"");
+
+ if (DEBUG_ROUTINE) Slog.e(LOGTAG, "found '" + word + "'");
+ parsed.add(word);
+
+ // find the beginning of the next word - either of these options
+ int nextSpace = rawEvent.indexOf(' ', current);
+ int nextQuote = rawEvent.indexOf(" \"", current);
+ if (DEBUG_ROUTINE) {
+ Slog.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote);
+ }
+ if (nextQuote > -1 && nextQuote <= nextSpace) {
+ quoted = true;
+ current = nextQuote + 2;
+ } else {
+ quoted = false;
+ if (nextSpace > -1) {
+ current = nextSpace + 1;
+ }
+ } // else we just start the next word after the current and read til the end
+ if (DEBUG_ROUTINE) {
+ Slog.e(LOGTAG, "next loop - current=" + current +
+ ", length=" + length + ", quoted=" + quoted);
+ }
}
+ return parsed.toArray(new String[parsed.size()]);
}
- }
- /**
- * Callback from NativeDaemonConnector
- */
- @Override
- public void onDaemonConnected() {
- mDaemonConnected = true;
- mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
- }
+ // @Override
+ public void onEvent(int code, String message)
+ throws android.os.RemoteException {
+ if (DEBUG)
+ Slog.d(TAG, "onEvent code=" + code + " message=" + message);
- private void handleDaemonConnected() {
- resetIfReadyAndConnected();
-
- /*
- * Now that we've done our initialization, release
- * the hounds!
- */
- mConnectedSignal.countDown();
- if (mConnectedSignal.getCount() != 0) {
- // More daemons need to connect
- return;
+ String[] cooked = unescapeArgs(message);
+ mDroidVoldManager.onEvent(code, message, unescapeArgs(message));
}
- }
- /**
- * Callback from NativeDaemonConnector
- */
- @Override
- public boolean onCheckHoldWakeLock(int code) {
- return false;
}
/**
* Callback from NativeDaemonConnector
*/
- @Override
public boolean onEvent(int code, String raw, String[] cooked) {
synchronized (mLock) {
return onEventLocked(code, raw, cooked);
@@ -410,26 +430,26 @@ class DroidVoldManager extends IDroidVoldManager.Stub
private boolean onEventLocked(int code, String raw, String[] cooked) {
switch (code) {
case VoldResponseCode.DISK_CREATED: {
- if (cooked.length != 3) break;
- final String id = cooked[1];
- int flags = Integer.parseInt(cooked[2]);
+ if (cooked.length != 2) break;
+ final String id = cooked[0];
+ int flags = Integer.parseInt(cooked[1]);
mDisks.put(id, new DiskInfo(id, flags));
break;
}
case VoldResponseCode.DISK_SIZE_CHANGED: {
- if (cooked.length != 3) break;
- final DiskInfo disk = mDisks.get(cooked[1]);
+ if (cooked.length != 2) break;
+ final DiskInfo disk = mDisks.get(cooked[0]);
if (disk != null) {
- disk.size = Long.parseLong(cooked[2]);
+ //disk.size = Long.parseLong(cooked[1]);
}
break;
}
case VoldResponseCode.DISK_LABEL_CHANGED: {
- final DiskInfo disk = mDisks.get(cooked[1]);
+ final DiskInfo disk = mDisks.get(cooked[0]);
if (disk != null) {
final StringBuilder builder = new StringBuilder();
- for (int i = 2; i < cooked.length; i++) {
+ for (int i = 1; i < cooked.length; i++) {
builder.append(cooked[i]).append(' ');
}
disk.label = builder.toString().trim();
@@ -437,29 +457,29 @@ class DroidVoldManager extends IDroidVoldManager.Stub
break;
}
case VoldResponseCode.DISK_SCANNED: {
- if (cooked.length != 2) break;
- final DiskInfo disk = mDisks.get(cooked[1]);
+ if (cooked.length != 1) break;
+ final DiskInfo disk = mDisks.get(cooked[0]);
break;
}
case VoldResponseCode.DISK_SYS_PATH_CHANGED: {
- if (cooked.length != 3) break;
- final DiskInfo disk = mDisks.get(cooked[1]);
+ if (cooked.length != 2) break;
+ final DiskInfo disk = mDisks.get(cooked[0]);
if (disk != null) {
- disk.sysPath = cooked[2];
+ disk.sysPath = cooked[1];
}
break;
}
case VoldResponseCode.DISK_DESTROYED: {
- if (cooked.length != 2) break;
- final DiskInfo disk = mDisks.remove(cooked[1]);
+ if (cooked.length != 1) break;
+ final DiskInfo disk = mDisks.remove(cooked[0]);
break;
}
case VoldResponseCode.VOLUME_CREATED: {
- final String id = cooked[1];
- final int type = Integer.parseInt(cooked[2]);
- final String diskId = TextUtils.nullIfEmpty(cooked[3]);
- final String partGuid = TextUtils.nullIfEmpty(cooked[4]);
+ final String id = cooked[0];
+ final int type = Integer.parseInt(cooked[1]);
+ final String diskId = TextUtils.nullIfEmpty(cooked[2]);
+ final String partGuid = TextUtils.nullIfEmpty(cooked[3]);
final DiskInfo disk = mDisks.get(diskId);
final VolumeInfo vol = new VolumeInfo(id, type, disk, partGuid);
@@ -468,37 +488,37 @@ class DroidVoldManager extends IDroidVoldManager.Stub
break;
}
case VoldResponseCode.VOLUME_STATE_CHANGED: {
- if (cooked.length != 3) break;
- final VolumeInfo vol = mVolumes.get(cooked[1]);
+ if (cooked.length != 2) break;
+ final VolumeInfo vol = mVolumes.get(cooked[0]);
if (vol != null) {
final int oldState = vol.state;
- final int newState = Integer.parseInt(cooked[2]);
+ final int newState = Integer.parseInt(cooked[1]);
vol.state = newState;
onVolumeStateChangedLocked(vol, oldState, newState);
}
break;
}
case VoldResponseCode.VOLUME_FS_TYPE_CHANGED: {
- if (cooked.length != 3) break;
- final VolumeInfo vol = mVolumes.get(cooked[1]);
+ if (cooked.length != 2) break;
+ final VolumeInfo vol = mVolumes.get(cooked[0]);
if (vol != null) {
- vol.fsType = cooked[2];
+ vol.fsType = cooked[1];
}
break;
}
case VoldResponseCode.VOLUME_FS_UUID_CHANGED: {
- if (cooked.length != 3) break;
- final VolumeInfo vol = mVolumes.get(cooked[1]);
+ if (cooked.length != 2) break;
+ final VolumeInfo vol = mVolumes.get(cooked[0]);
if (vol != null) {
- vol.fsUuid = cooked[2];
+ vol.fsUuid = cooked[1];
}
break;
}
case VoldResponseCode.VOLUME_FS_LABEL_CHANGED: {
- final VolumeInfo vol = mVolumes.get(cooked[1]);
+ final VolumeInfo vol = mVolumes.get(cooked[0]);
if (vol != null) {
final StringBuilder builder = new StringBuilder();
- for (int i = 2; i < cooked.length; i++) {
+ for (int i = 1; i < cooked.length; i++) {
builder.append(cooked[i]).append(' ');
}
vol.fsLabel = builder.toString().trim();
@@ -506,24 +526,24 @@ class DroidVoldManager extends IDroidVoldManager.Stub
break;
}
case VoldResponseCode.VOLUME_PATH_CHANGED: {
- if (cooked.length != 3) break;
- final VolumeInfo vol = mVolumes.get(cooked[1]);
+ if (cooked.length != 2) break;
+ final VolumeInfo vol = mVolumes.get(cooked[0]);
if (vol != null) {
- vol.path = cooked[2];
+ vol.path = cooked[1];
}
break;
}
case VoldResponseCode.VOLUME_INTERNAL_PATH_CHANGED: {
- if (cooked.length != 3) break;
- final VolumeInfo vol = mVolumes.get(cooked[1]);
+ if (cooked.length != 2) break;
+ final VolumeInfo vol = mVolumes.get(cooked[0]);
if (vol != null) {
- vol.internalPath = cooked[2];
+ vol.internalPath = cooked[1];
}
break;
}
case VoldResponseCode.VOLUME_DESTROYED: {
- if (cooked.length != 2) break;
- mVolumes.remove(cooked[1]);
+ if (cooked.length != 1) break;
+ mVolumes.remove(cooked[0]);
break;
}
@@ -538,7 +558,6 @@ class DroidVoldManager extends IDroidVoldManager.Stub
private void onVolumeCreatedLocked(VolumeInfo vol) {
if (vol.type == VolumeInfo.TYPE_PUBLIC) {
-
// Adoptable public disks are visible to apps, since they meet
// public API requirement of being in a stable location.
vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
@@ -578,9 +597,10 @@ class DroidVoldManager extends IDroidVoldManager.Stub
// Kick state changed event towards all started users. Any users
// started after this point will trigger additional
// user-specific broadcasts.
- final StorageVolume userVol = vol.buildStorageVolume(mContext, mCurrentUserId, false);
- mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
-
+ if (vol.path != null) {
+ final StorageVolume userVol = vol.buildStorageVolume(mContext, mCurrentUserId, false);
+ mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
+ }
}
}
@@ -617,30 +637,30 @@ class DroidVoldManager extends IDroidVoldManager.Stub
*/
public DroidVoldManager(Context context) {
sSelf = this;
-
mContext = context;
- Slog.d(TAG, "start handle");
HandlerThread hthread = new HandlerThread(TAG);
hthread.start();
mHandler = new DroidVoldManagerHandler(hthread.getLooper());
- // LocalServices.addService(StorageManagerInternal.class, mStorageManagerInternal);
-
- /*
- * Create the connection to vold with a maximum queue of twice the
- * amount of containers we'd ever expect to have. This keeps an
- * "asec list" from blocking a thread repeatedly.
- */
+ try {
+ mDroidVold = IDroidVold.getService();
+ mDroidVoldCallback = new DroidVoldCallback(this);
+
+ if (DEBUG) Slog.d(TAG, "setCallback");
+ mDroidVold.setCallback(mDroidVoldCallback);
+ mDroidVold.linkToDeath(new DeathRecipient(), 0);
+
+ } catch (NoSuchElementException e) {
+ Slog.e(TAG, "connectToProxy: droidvold hal service not found."
+ + " Did the service fail to start?", e);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "connectToProxy: droidvold hal service not responding", e);
+ }
- mConnector = new NativeDaemonConnector(this, "droidvold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
- null, hthread.getLooper());
- mConnector.setDebug(true);
- mConnector.setWarnIfHeld(mLock);
+ if (DEBUG) Slog.d(TAG, "restIfReady and connected");
+ resetIfReadyAndConnected();
- mConnectorThread = new Thread(mConnector, VOLD_TAG);
- Slog.d(TAG, "start nativeNaemon");
- mConnectorThread.start();
ServiceManager.addService("droidmount", sSelf, false);
}
@@ -686,6 +706,8 @@ class DroidVoldManager extends IDroidVoldManager.Stub
@Override
public int mkdirs(String callingPkg, String appPath) {
+ //ignore
+ /*
final int userId = UserHandle.getUserId(Binder.getCallingUid());
final UserEnvironment userEnv = new UserEnvironment(userId);
@@ -716,6 +738,8 @@ class DroidVoldManager extends IDroidVoldManager.Stub
}
throw new SecurityException("Invalid mkdirs path: " + appFile);
+ */
+ return 0;
}
@Override
@@ -831,43 +855,41 @@ class DroidVoldManager extends IDroidVoldManager.Stub
@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();
+ mDroidVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "connectToProxy: droidvold hal service not responding", e);
}
}
@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();
+ mDroidVold.unmount(vol.id);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "connectToProxy: droidvold hal service not responding", e);
}
}
@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();
+ mDroidVold.format(vol.id, "auto");
+ } catch (RemoteException e) {
+ Slog.e(TAG, "connectToProxy: droidvold hal service not responding", e);
}
}
@@ -940,14 +962,9 @@ class DroidVoldManager extends IDroidVoldManager.Stub
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();
}
}
diff --git a/core/res/src/com/droidlogic/INativeDaemonConnectorCallbacks.java b/core/res/src/com/droidlogic/INativeDaemonConnectorCallbacks.java
deleted file mode 100644
index 7a7014e..0000000
--- a/core/res/src/com/droidlogic/INativeDaemonConnectorCallbacks.java
+++ b/dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-package com.droidlogic;
-
-interface INativeDaemonConnectorCallbacks {
-
- void onDaemonConnected();
- boolean onCheckHoldWakeLock(int code);
- boolean onEvent(int code, String raw, String[] cooked);
-}
diff --git a/core/res/src/com/droidlogic/NativeDaemonConnector.java b/core/res/src/com/droidlogic/NativeDaemonConnector.java
deleted file mode 100644
index 56727a6..0000000
--- a/core/res/src/com/droidlogic/NativeDaemonConnector.java
+++ b/dev/null
@@ -1,701 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-package com.droidlogic;
-
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.util.LocalLog;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
-import com.google.android.collect.Lists;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.LinkedList;
-
-/**
- * Generic connector class for interfacing with a native daemon which uses the
- * {@code libsysutils} FrameworkListener protocol.
- */
-final class NativeDaemonConnector implements Runnable, Handler.Callback {
- private final static boolean VDBG = false;
-
- private final String TAG;
-
- private String mSocket;
- private OutputStream mOutputStream;
- private LocalLog mLocalLog;
-
- private volatile boolean mDebug = false;
- private volatile Object mWarnIfHeld;
-
- private final ResponseQueue mResponseQueue;
-
- private final PowerManager.WakeLock mWakeLock;
-
- private final Looper mLooper;
-
- private INativeDaemonConnectorCallbacks mCallbacks;
- private Handler mCallbackHandler;
-
- private AtomicInteger mSequenceNumber;
-
- private static final long DEFAULT_TIMEOUT = 1 * 60 * 1000; /* 1 minute */
- private static final long WARN_EXECUTE_DELAY_MS = 500; /* .5 sec */
-
- /** Lock held whenever communicating with native daemon. */
- private final Object mDaemonLock = new Object();
-
- private final int BUFFER_SIZE = 4096;
-
- NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
- int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl,
- Looper looper) {
- mCallbacks = callbacks;
- mSocket = socket;
- mResponseQueue = new ResponseQueue(responseQueueSize);
- mWakeLock = wl;
- if (mWakeLock != null) {
- mWakeLock.setReferenceCounted(true);
- }
- mLooper = looper;
- mSequenceNumber = new AtomicInteger(0);
- TAG = logTag != null ? logTag : "NativeDaemonConnector";
- mLocalLog = new LocalLog(maxLogSize);
- }
-
- /**
- * Enable Set debugging mode, which causes messages to also be written to both
- * {@link Slog} in addition to internal log.
- */
- public void setDebug(boolean debug) {
- mDebug = debug;
- }
-
- /**
- * Like SystemClock.uptimeMillis, except truncated to an int so it will fit in a message arg.
- * Inaccurate across 49.7 days of uptime, but only used for debugging.
- */
- private int uptimeMillisInt() {
- return (int) SystemClock.uptimeMillis() & Integer.MAX_VALUE;
- }
-
- /**
- * Yell loudly if someone tries making future {@link #execute(Command)}
- * calls while holding a lock on the given object.
- */
- public void setWarnIfHeld(Object warnIfHeld) {
- Preconditions.checkState(mWarnIfHeld == null);
- mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
- }
-
- @Override
- public void run() {
- mCallbackHandler = new Handler(mLooper, this);
-
- while (true) {
- try {
- listenToSocket();
- } catch (Exception e) {
- loge("Error in NativeDaemonConnector: " + e);
- SystemClock.sleep(5000);
- }
- }
- }
-
- @Override
- public boolean handleMessage(Message msg) {
- final String event = (String) msg.obj;
- final int start = uptimeMillisInt();
- final int sent = msg.arg1;
- try {
- if (!mCallbacks.onEvent(msg.what, event, NativeDaemonEvent.unescapeArgs(event))) {
- log(String.format("Unhandled event '%s'", event));
- }
- } catch (Exception e) {
- loge("Error handling '" + event + "': " + e);
- } finally {
- if (mCallbacks.onCheckHoldWakeLock(msg.what) && mWakeLock != null) {
- mWakeLock.release();
- }
- final int end = uptimeMillisInt();
- if (start > sent && start - sent > WARN_EXECUTE_DELAY_MS) {
- loge(String.format("NDC event {%s} processed too late: %dms", event, start - sent));
- }
- if (end > start && end - start > WARN_EXECUTE_DELAY_MS) {
- loge(String.format("NDC event {%s} took too long: %dms", event, end - start));
- }
- }
- return true;
- }
-
- private LocalSocketAddress determineSocketAddress() {
- // If we're testing, set up a socket in a namespace that's accessible to test code.
- // In order to ensure that unprivileged apps aren't able to impersonate native daemons on
- // production devices, even if said native daemons ill-advisedly pick a socket name that
- // starts with __test__, only allow this on debug builds.
- if (mSocket.startsWith("__test__") && Build.IS_DEBUGGABLE) {
- return new LocalSocketAddress(mSocket);
- } else {
- return new LocalSocketAddress(mSocket, LocalSocketAddress.Namespace.RESERVED);
- }
- }
-
- private void listenToSocket() throws IOException {
- LocalSocket socket = null;
-
- try {
- socket = new LocalSocket();
- LocalSocketAddress address = determineSocketAddress();
-
- socket.connect(address);
-
- InputStream inputStream = socket.getInputStream();
- synchronized (mDaemonLock) {
- mOutputStream = socket.getOutputStream();
- }
-
- mCallbacks.onDaemonConnected();
-
- FileDescriptor[] fdList = null;
- byte[] buffer = new byte[BUFFER_SIZE];
- int start = 0;
-
- while (true) {
- int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
- if (count < 0) {
- loge("got " + count + " reading with start = " + start);
- break;
- }
- fdList = socket.getAncillaryFileDescriptors();
-
- // Add our starting point to the count and reset the start.
- count += start;
- start = 0;
-
- for (int i = 0; i < count; i++) {
- if (buffer[i] == 0) {
- // Note - do not log this raw message since it may contain
- // sensitive data
- final String rawEvent = new String(
- buffer, start, i - start, StandardCharsets.UTF_8);
-
- boolean releaseWl = false;
- try {
- final NativeDaemonEvent event =
- NativeDaemonEvent.parseRawEvent(rawEvent, fdList);
-
- log("RCV <- {" + event + "}");
-
- if (event.isClassUnsolicited()) {
- // TODO: migrate to sending NativeDaemonEvent instances
- if (mCallbacks.onCheckHoldWakeLock(event.getCode())
- && mWakeLock != null) {
- mWakeLock.acquire();
- releaseWl = true;
- }
- Message msg = mCallbackHandler.obtainMessage(
- event.getCode(), uptimeMillisInt(), 0, event.getRawEvent());
- if (mCallbackHandler.sendMessage(msg)) {
- releaseWl = false;
- }
- } else {
- mResponseQueue.add(event.getCmdNumber(), event);
- }
- } catch (IllegalArgumentException e) {
- log("Problem parsing message " + e);
- } finally {
- if (releaseWl) {
- mWakeLock.release();
- }
- }
-
- start = i + 1;
- }
- }
-
- if (start == 0) {
- log("RCV incomplete");
- }
-
- // We should end at the amount we read. If not, compact then
- // buffer and read again.
- if (start != count) {
- final int remaining = BUFFER_SIZE - start;
- System.arraycopy(buffer, start, buffer, 0, remaining);
- start = remaining;
- } else {
- start = 0;
- }
- }
- } catch (IOException ex) {
- loge("Communications error: " + ex);
- throw ex;
- } finally {
- synchronized (mDaemonLock) {
- if (mOutputStream != null) {
- try {
- loge("closing stream for " + mSocket);
- mOutputStream.close();
- } catch (IOException e) {
- loge("Failed closing output stream: " + e);
- }
- mOutputStream = null;
- }
- }
-
- try {
- if (socket != null) {
- socket.close();
- }
- } catch (IOException ex) {
- loge("Failed closing socket: " + ex);
- }
- }
- }
-
- /**
- * Wrapper around argument that indicates it's sensitive and shouldn't be
- * logged.
- */
- public static class SensitiveArg {
- private final Object mArg;
-
- public SensitiveArg(Object arg) {
- mArg = arg;
- }
-
- @Override
- public String toString() {
- return String.valueOf(mArg);
- }
- }
-
- /**
- * Make command for daemon, escaping arguments as needed.
- */
- @VisibleForTesting
- static void makeCommand(StringBuilder rawBuilder, StringBuilder logBuilder, int sequenceNumber,
- String cmd, Object... args) {
- if (cmd.indexOf('\0') >= 0) {
- throw new IllegalArgumentException("Unexpected command: " + cmd);
- }
- if (cmd.indexOf(' ') >= 0) {
- throw new IllegalArgumentException("Arguments must be separate from command");
- }
-
- rawBuilder.append(sequenceNumber).append(' ').append(cmd);
- logBuilder.append(sequenceNumber).append(' ').append(cmd);
- for (Object arg : args) {
- final String argString = String.valueOf(arg);
- if (argString.indexOf('\0') >= 0) {
- throw new IllegalArgumentException("Unexpected argument: " + arg);
- }
-
- rawBuilder.append(' ');
- logBuilder.append(' ');
-
- appendEscaped(rawBuilder, argString);
- if (arg instanceof SensitiveArg) {
- logBuilder.append("[scrubbed]");
- } else {
- appendEscaped(logBuilder, argString);
- }
- }
-
- rawBuilder.append('\0');
- }
-
- /**
- * Method that waits until all asychronous notifications sent by the native daemon have
- * been processed. This method must not be called on the notification thread or an
- * exception will be thrown.
- */
- public void waitForCallbacks() {
- if (Thread.currentThread() == mLooper.getThread()) {
- throw new IllegalStateException("Must not call this method on callback thread");
- }
-
- final CountDownLatch latch = new CountDownLatch(1);
- mCallbackHandler.post(new Runnable() {
- @Override
- public void run() {
- latch.countDown();
- }
- });
- try {
- latch.await();
- } catch (InterruptedException e) {
- Slog.wtf(TAG, "Interrupted while waiting for unsolicited response handling", e);
- }
- }
-
- /**
- * Issue the given command to the native daemon and return a single expected
- * response.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent execute(Command cmd) throws NativeDaemonConnectorException {
- return execute(cmd.mCmd, cmd.mArguments.toArray());
- }
-
- /**
- * Issue the given command to the native daemon and return a single expected
- * response. Any arguments must be separated from base command so they can
- * be properly escaped.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent execute(String cmd, Object... args)
- throws NativeDaemonConnectorException {
- return execute(DEFAULT_TIMEOUT, cmd, args);
- }
-
- public NativeDaemonEvent execute(long timeoutMs, String cmd, Object... args)
- throws NativeDaemonConnectorException {
- final NativeDaemonEvent[] events = executeForList(timeoutMs, cmd, args);
- if (events.length != 1) {
- throw new NativeDaemonConnectorException(
- "Expected exactly one response, but received " + events.length);
- }
- return events[0];
- }
-
- /**
- * Issue the given command to the native daemon and return any
- * {@link NativeDaemonEvent#isClassContinue()} responses, including the
- * final terminal response.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent[] executeForList(Command cmd) throws NativeDaemonConnectorException {
- return executeForList(cmd.mCmd, cmd.mArguments.toArray());
- }
-
- /**
- * Issue the given command to the native daemon and return any
- * {@link NativeDaemonEvent#isClassContinue()} responses, including the
- * final terminal response. Any arguments must be separated from base
- * command so they can be properly escaped.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent[] executeForList(String cmd, Object... args)
- throws NativeDaemonConnectorException {
- return executeForList(DEFAULT_TIMEOUT, cmd, args);
- }
-
- /**
- * Issue the given command to the native daemon and return any {@linke
- * NativeDaemonEvent@isClassContinue()} responses, including the final
- * terminal response. Note that the timeout does not count time in deep
- * sleep. Any arguments must be separated from base command so they can be
- * properly escaped.
- *
- * @throws NativeDaemonConnectorException when problem communicating with
- * native daemon, or if the response matches
- * {@link NativeDaemonEvent#isClassClientError()} or
- * {@link NativeDaemonEvent#isClassServerError()}.
- */
- public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
- throws NativeDaemonConnectorException {
- if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
- Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
- + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
- }
-
- final long startTime = SystemClock.elapsedRealtime();
-
- final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
-
- final StringBuilder rawBuilder = new StringBuilder();
- final StringBuilder logBuilder = new StringBuilder();
- final int sequenceNumber = mSequenceNumber.incrementAndGet();
-
- makeCommand(rawBuilder, logBuilder, sequenceNumber, cmd, args);
-
- final String rawCmd = rawBuilder.toString();
- final String logCmd = logBuilder.toString();
-
- log("SND -> {" + logCmd + "}");
-
- synchronized (mDaemonLock) {
- if (mOutputStream == null) {
- throw new NativeDaemonConnectorException("missing output stream");
- } else {
- try {
- mOutputStream.write(rawCmd.getBytes(StandardCharsets.UTF_8));
- } catch (IOException e) {
- throw new NativeDaemonConnectorException("problem sending command", e);
- }
- }
- }
-
- NativeDaemonEvent event = null;
- do {
- event = mResponseQueue.remove(sequenceNumber, timeoutMs, logCmd);
- if (event == null) {
- loge("timed-out waiting for response to " + logCmd);
- throw new NativeDaemonTimeoutException(logCmd, event);
- }
- if (VDBG) log("RMV <- {" + event + "}");
- events.add(event);
- } while (event.isClassContinue());
-
- final long endTime = SystemClock.elapsedRealtime();
- if (endTime - startTime > WARN_EXECUTE_DELAY_MS) {
- loge("NDC Command {" + logCmd + "} took too long (" + (endTime - startTime) + "ms)");
- }
-
- if (event.isClassClientError()) {
- throw new NativeDaemonArgumentException(logCmd, event);
- }
- if (event.isClassServerError()) {
- throw new NativeDaemonFailureException(logCmd, event);
- }
-
- return events.toArray(new NativeDaemonEvent[events.size()]);
- }
-
- /**
- * Append the given argument to {@link StringBuilder}, escaping as needed,
- * and surrounding with quotes when it contains spaces.
- */
- @VisibleForTesting
- static void appendEscaped(StringBuilder builder, String arg) {
- final boolean hasSpaces = arg.indexOf(' ') >= 0;
- if (hasSpaces) {
- builder.append('"');
- }
-
- final int length = arg.length();
- for (int i = 0; i < length; i++) {
- final char c = arg.charAt(i);
-
- if (c == '"') {
- builder.append("\\\"");
- } else if (c == '\\') {
- builder.append("\\\\");
- } else {
- builder.append(c);
- }
- }
-
- if (hasSpaces) {
- builder.append('"');
- }
- }
-
- private static class NativeDaemonArgumentException extends NativeDaemonConnectorException {
- public NativeDaemonArgumentException(String command, NativeDaemonEvent event) {
- super(command, event);
- }
-
- @Override
- public IllegalArgumentException rethrowAsParcelableException() {
- throw new IllegalArgumentException(getMessage(), this);
- }
- }
-
- private static class NativeDaemonFailureException extends NativeDaemonConnectorException {
- public NativeDaemonFailureException(String command, NativeDaemonEvent event) {
- super(command, event);
- }
- }
-
- /**
- * Command builder that handles argument list building. Any arguments must
- * be separated from base command so they can be properly escaped.
- */
- public static class Command {
- private String mCmd;
- private ArrayList<Object> mArguments = Lists.newArrayList();
-
- public Command(String cmd, Object... args) {
- mCmd = cmd;
- for (Object arg : args) {
- appendArg(arg);
- }
- }
-
- public Command appendArg(Object arg) {
- mArguments.add(arg);
- return this;
- }
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mLocalLog.dump(fd, pw, args);
- pw.println();
- mResponseQueue.dump(fd, pw, args);
- }
-
- private void log(String logstring) {
- if (mDebug) Slog.d(TAG, logstring);
- mLocalLog.log(logstring);
- }
-
- private void loge(String logstring) {
- Slog.e(TAG, logstring);
- mLocalLog.log(logstring);
- }
-
- private static class ResponseQueue {
-
- private static class PendingCmd {
- public final int cmdNum;
- public final String logCmd;
-
- public BlockingQueue<NativeDaemonEvent> responses =
- new ArrayBlockingQueue<NativeDaemonEvent>(10);
-
- // The availableResponseCount member is used to track when we can remove this
- // instance from the ResponseQueue.
- // This is used under the protection of a sync of the mPendingCmds object.
- // A positive value means we've had more writers retreive this object while
- // a negative value means we've had more readers. When we've had an equal number
- // (it goes to zero) we can remove this object from the mPendingCmds list.
- // Note that we may have more responses for this command (and more readers
- // coming), but that would result in a new PendingCmd instance being created
- // and added with the same cmdNum.
- // Also note that when this goes to zero it just means a parity of readers and
- // writers have retrieved this object - not that they are done using it. The
- // responses queue may well have more responses yet to be read or may get more
- // responses added to it. But all those readers/writers have retreived and
- // hold references to this instance already so it can be removed from
- // mPendingCmds queue.
- public int availableResponseCount;
-
- public PendingCmd(int cmdNum, String logCmd) {
- this.cmdNum = cmdNum;
- this.logCmd = logCmd;
- }
- }
-
- private final LinkedList<PendingCmd> mPendingCmds;
- private int mMaxCount;
-
- ResponseQueue(int maxCount) {
- mPendingCmds = new LinkedList<PendingCmd>();
- mMaxCount = maxCount;
- }
-
- public void add(int cmdNum, NativeDaemonEvent response) {
- PendingCmd found = null;
- synchronized (mPendingCmds) {
- for (PendingCmd pendingCmd : mPendingCmds) {
- if (pendingCmd.cmdNum == cmdNum) {
- found = pendingCmd;
- break;
- }
- }
- if (found == null) {
- // didn't find it - make sure our queue isn't too big before adding
- while (mPendingCmds.size() >= mMaxCount) {
- Slog.e("NativeDaemonConnector.ResponseQueue",
- "more buffered than allowed: " + mPendingCmds.size() +
- " >= " + mMaxCount);
- // let any waiter timeout waiting for this
- PendingCmd pendingCmd = mPendingCmds.remove();
- Slog.e("NativeDaemonConnector.ResponseQueue",
- "Removing request: " + pendingCmd.logCmd + " (" +
- pendingCmd.cmdNum + ")");
- }
- found = new PendingCmd(cmdNum, null);
- mPendingCmds.add(found);
- }
- found.availableResponseCount++;
- // if a matching remove call has already retrieved this we can remove this
- // instance from our list
- if (found.availableResponseCount == 0) mPendingCmds.remove(found);
- }
- try {
- found.responses.put(response);
- } catch (InterruptedException e) { }
- }
-
- // note that the timeout does not count time in deep sleep. If you don't want
- // the device to sleep, hold a wakelock
- public NativeDaemonEvent remove(int cmdNum, long timeoutMs, String logCmd) {
- PendingCmd found = null;
- synchronized (mPendingCmds) {
- for (PendingCmd pendingCmd : mPendingCmds) {
- if (pendingCmd.cmdNum == cmdNum) {
- found = pendingCmd;
- break;
- }
- }
- if (found == null) {
- found = new PendingCmd(cmdNum, logCmd);
- mPendingCmds.add(found);
- }
- found.availableResponseCount--;
- // if a matching add call has already retrieved this we can remove this
- // instance from our list
- if (found.availableResponseCount == 0) mPendingCmds.remove(found);
- }
- NativeDaemonEvent result = null;
- try {
- result = found.responses.poll(timeoutMs, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {}
- if (result == null) {
- Slog.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
- }
- return result;
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("Pending requests:");
- synchronized (mPendingCmds) {
- for (PendingCmd pendingCmd : mPendingCmds) {
- pw.println(" Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.logCmd);
- }
- }
- }
- }
-}
diff --git a/core/res/src/com/droidlogic/NativeDaemonConnectorException.java b/core/res/src/com/droidlogic/NativeDaemonConnectorException.java
deleted file mode 100644
index 3911c98..0000000
--- a/core/res/src/com/droidlogic/NativeDaemonConnectorException.java
+++ b/dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-package com.droidlogic;
-
-import android.os.Parcel;
-
-/**
- * An exception that indicates there was an error with a
- * {@link NativeDaemonConnector} operation.
- */
-public class NativeDaemonConnectorException extends Exception {
- private String mCmd;
- private NativeDaemonEvent mEvent;
-
- public NativeDaemonConnectorException(String detailMessage) {
- super(detailMessage);
- }
-
- public NativeDaemonConnectorException(String detailMessage, Throwable throwable) {
- super(detailMessage, throwable);
- }
-
- public NativeDaemonConnectorException(String cmd, NativeDaemonEvent event) {
- super("command '" + cmd + "' failed with '" + event + "'");
- mCmd = cmd;
- mEvent = event;
- }
-
- public int getCode() {
- return mEvent != null ? mEvent.getCode() : -1;
- }
-
- public String getCmd() {
- return mCmd;
- }
-
- /**
- * Rethrow as a {@link RuntimeException} subclass that is handled by
- * {@link Parcel#writeException(Exception)}.
- */
- public IllegalArgumentException rethrowAsParcelableException() {
- throw new IllegalStateException(getMessage(), this);
- }
-}
diff --git a/core/res/src/com/droidlogic/NativeDaemonEvent.java b/core/res/src/com/droidlogic/NativeDaemonEvent.java
deleted file mode 100644
index eee61b6..0000000
--- a/core/res/src/com/droidlogic/NativeDaemonEvent.java
+++ b/dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-package com.droidlogic;
-
-import android.util.Slog;
-import com.google.android.collect.Lists;
-
-import java.io.FileDescriptor;
-import java.util.ArrayList;
-
-/**
- * Parsed event from native side of {@link NativeDaemonConnector}.
- */
-public class NativeDaemonEvent {
-
- // TODO: keep class ranges in sync with ResponseCode.h
- // TODO: swap client and server error ranges to roughly mirror HTTP spec
-
- private final int mCmdNumber;
- private final int mCode;
- private final String mMessage;
- private final String mRawEvent;
- private final String mLogMessage;
- private String[] mParsed;
- private FileDescriptor[] mFdList;
-
- private NativeDaemonEvent(int cmdNumber, int code, String message,
- String rawEvent, String logMessage, FileDescriptor[] fdList) {
- mCmdNumber = cmdNumber;
- mCode = code;
- mMessage = message;
- mRawEvent = rawEvent;
- mLogMessage = logMessage;
- mParsed = null;
- mFdList = fdList;
- }
-
- static public final String SENSITIVE_MARKER = "{{sensitive}}";
-
- public int getCmdNumber() {
- return mCmdNumber;
- }
-
- public int getCode() {
- return mCode;
- }
-
- public String getMessage() {
- return mMessage;
- }
-
- public FileDescriptor[] getFileDescriptors() {
- return mFdList;
- }
-
- @Deprecated
- public String getRawEvent() {
- return mRawEvent;
- }
-
- @Override
- public String toString() {
- return mLogMessage;
- }
-
- /**
- * Test if event represents a partial response which is continued in
- * additional subsequent events.
- */
- public boolean isClassContinue() {
- return mCode >= 100 && mCode < 200;
- }
-
- /**
- * Test if event represents a command success.
- */
- public boolean isClassOk() {
- return mCode >= 200 && mCode < 300;
- }
-
- /**
- * Test if event represents a remote native daemon error.
- */
- public boolean isClassServerError() {
- return mCode >= 400 && mCode < 500;
- }
-
- /**
- * Test if event represents a command syntax or argument error.
- */
- public boolean isClassClientError() {
- return mCode >= 500 && mCode < 600;
- }
-
- /**
- * Test if event represents an unsolicited event from native daemon.
- */
- public boolean isClassUnsolicited() {
- return isClassUnsolicited(mCode);
- }
-
- private static boolean isClassUnsolicited(int code) {
- return code >= 600 && code < 700;
- }
-
- /**
- * Verify this event matches the given code.
- *
- * @throws IllegalStateException if {@link #getCode()} doesn't match.
- */
- public void checkCode(int code) {
- if (mCode != code) {
- throw new IllegalStateException("Expected " + code + " but was: " + this);
- }
- }
-
- /**
- * Parse the given raw event into {@link NativeDaemonEvent} instance.
- *
- * @throws IllegalArgumentException when line doesn't match format expected
- * from native side.
- */
- public static NativeDaemonEvent parseRawEvent(String rawEvent, FileDescriptor[] fdList) {
- final String[] parsed = rawEvent.split(" ");
- if (parsed.length < 2) {
- throw new IllegalArgumentException("Insufficient arguments");
- }
-
- int skiplength = 0;
-
- final int code;
- try {
- code = Integer.parseInt(parsed[0]);
- skiplength = parsed[0].length() + 1;
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("problem parsing code", e);
- }
-
- int cmdNumber = -1;
- if (isClassUnsolicited(code) == false) {
- if (parsed.length < 3) {
- throw new IllegalArgumentException("Insufficient arguemnts");
- }
- try {
- cmdNumber = Integer.parseInt(parsed[1]);
- skiplength += parsed[1].length() + 1;
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("problem parsing cmdNumber", e);
- }
- }
-
- String logMessage = rawEvent;
- if (parsed.length > 2 && parsed[2].equals(SENSITIVE_MARKER)) {
- skiplength += parsed[2].length() + 1;
- logMessage = parsed[0] + " " + parsed[1] + " {}";
- }
-
- final String message = rawEvent.substring(skiplength);
-
- return new NativeDaemonEvent(cmdNumber, code, message, rawEvent, logMessage, fdList);
- }
-
- /**
- * Filter the given {@link NativeDaemonEvent} list, returning
- * {@link #getMessage()} for any events matching the requested code.
- */
- public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) {
- final ArrayList<String> result = Lists.newArrayList();
- for (NativeDaemonEvent event : events) {
- if (event.getCode() == matchCode) {
- result.add(event.getMessage());
- }
- }
- return result.toArray(new String[result.size()]);
- }
-
- /**
- * Find the Nth field of the event.
- *
- * This ignores and code or cmdNum, the first return value is given for N=0.
- * Also understands "\"quoted\" multiword responses" and tries them as a single field
- */
- public String getField(int n) {
- if (mParsed == null) {
- mParsed = unescapeArgs(mRawEvent);
- }
- n += 2; // skip code and command#
- if (n > mParsed.length) return null;
- return mParsed[n];
- }
-
- public static String[] unescapeArgs(String rawEvent) {
- final boolean DEBUG_ROUTINE = false;
- final String LOGTAG = "unescapeArgs";
- final ArrayList<String> parsed = new ArrayList<String>();
- final int length = rawEvent.length();
- int current = 0;
- int wordEnd = -1;
- boolean quoted = false;
-
- if (DEBUG_ROUTINE) Slog.e(LOGTAG, "parsing '" + rawEvent + "'");
- if (rawEvent.charAt(current) == '\"') {
- quoted = true;
- current++;
- }
- while (current < length) {
- // find the end of the word
- char terminator = quoted ? '\"' : ' ';
- wordEnd = current;
- while (wordEnd < length && rawEvent.charAt(wordEnd) != terminator) {
- if (rawEvent.charAt(wordEnd) == '\\') {
- // skip the escaped char
- ++wordEnd;
- }
- ++wordEnd;
- }
- if (wordEnd > length) wordEnd = length;
- String word = rawEvent.substring(current, wordEnd);
- current += word.length();
- if (!quoted) {
- word = word.trim();
- } else {
- current++; // skip the trailing quote
- }
- // unescape stuff within the word
- word = word.replace("\\\\", "\\");
- word = word.replace("\\\"", "\"");
-
- if (DEBUG_ROUTINE) Slog.e(LOGTAG, "found '" + word + "'");
- parsed.add(word);
-
- // find the beginning of the next word - either of these options
- int nextSpace = rawEvent.indexOf(' ', current);
- int nextQuote = rawEvent.indexOf(" \"", current);
- if (DEBUG_ROUTINE) {
- Slog.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote);
- }
- if (nextQuote > -1 && nextQuote <= nextSpace) {
- quoted = true;
- current = nextQuote + 2;
- } else {
- quoted = false;
- if (nextSpace > -1) {
- current = nextSpace + 1;
- }
- } // else we just start the next word after the current and read til the end
- if (DEBUG_ROUTINE) {
- Slog.e(LOGTAG, "next loop - current=" + current +
- ", length=" + length + ", quoted=" + quoted);
- }
- }
- return parsed.toArray(new String[parsed.size()]);
- }
-}
diff --git a/core/res/src/com/droidlogic/NativeDaemonTimeoutException.java b/core/res/src/com/droidlogic/NativeDaemonTimeoutException.java
deleted file mode 100644
index 16626e4..0000000
--- a/core/res/src/com/droidlogic/NativeDaemonTimeoutException.java
+++ b/dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-package com.droidlogic;
-
-/**
- * An exception that indicates there was a timeout with a
- * {@link NativeDaemonConnector} operation.
- */
-public class NativeDaemonTimeoutException extends NativeDaemonConnectorException {
- public NativeDaemonTimeoutException(String command, NativeDaemonEvent event) {
- super(command, event);
- }
-}
-