author | Baocheng 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) |
commit | af58a906e0f479a81a798103aaf54a174a183936 (patch) | |
tree | aeb01b6c2b40df99d88de3e9150957a0ea2ced59 | |
parent | 435ff173bd08cfe9939b4b044ad646d6d075855e (diff) | |
download | frameworks-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
-rw-r--r-- | core/res/Android.mk | 7 | ||||
-rw-r--r-- | core/res/src/com/droidlogic/DroidVoldManager.java | 395 | ||||
-rw-r--r-- | core/res/src/com/droidlogic/INativeDaemonConnectorCallbacks.java | 24 | ||||
-rw-r--r-- | core/res/src/com/droidlogic/NativeDaemonConnector.java | 701 | ||||
-rw-r--r-- | core/res/src/com/droidlogic/NativeDaemonConnectorException.java | 58 | ||||
-rw-r--r-- | core/res/src/com/droidlogic/NativeDaemonEvent.java | 268 | ||||
-rw-r--r-- | core/res/src/com/droidlogic/NativeDaemonTimeoutException.java | 28 |
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); - } -} - |