Reputation: 2198
In an open-source Camera App, I have a crash at the following code
try {
// crash happens in next line:
PtpUsbConnection connection = new PtpUsbConnection(usbManager.openDevice(device), in, out,
device.getVendorId(), device.getProductId());
camera = new EosCamera(connection, listener, new WorkerNotifier(context));
}
catch (IllegalArgumentException e) {
Log.i(TAG, "IllegalArgumentException: camera was switched off? "+ e.getMessage());
e.printStackTrace();
return false;
}
catch (Exception e) {
Log.i(TAG, "Exception: camera was switched off? "+ e.getMessage());
e.printStackTrace();
return false;
}
The crash produces the following log
02-25 10:41:14.698 9238-9238/com.remoteyourcam.usb E/UsbManager﹕ exception in UsbManager.openDevice
java.lang.IllegalArgumentException: device /dev/bus/usb/001/008 does not exist or is restricted
at android.os.Parcel.readException(Parcel.java:1469)
at android.os.Parcel.readException(Parcel.java:1419)
at android.hardware.usb.IUsbManager$Stub$Proxy.openDevice(IUsbManager.java:373)
at android.hardware.usb.UsbManager.openDevice(UsbManager.java:308)
at com.remoteyourcam.usb.ptp.PtpUsbService.connect(PtpUsbService.java:238)
at com.remoteyourcam.usb.ptp.PtpUsbService.initialize(PtpUsbService.java:135)
at com.remoteyourcam.usb.MainActivity.onStart(MainActivity.java:232)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
at android.app.Activity.performStart(Activity.java:5413)
at android.app.Activity.performRestart(Activity.java:5469)
at android.app.Activity.performResume(Activity.java:5474)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2945)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2984)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1335)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:788)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:604)
at dalvik.system.NativeStart.main(Native Method)
There is a reproducible sequence of events which causes the crash. Specifically: switching of the camera on the USB bus when the App (apparently) does not foresee the possibility.
I was hoping to simply catch this Exception and then ignore it.
However, even though the code explicity catches IllegalArgumentException
and also (for good measure) the general Exception
, the App simply continues to crash.
Why is my IllegalArgumentException
not being caught?
---- update:
The openDevice() method is part of Android Library. It actually seems to handle Exception
.
Here are my imports
package com.remoteyourcam.usb.ptp;
import java.util.Map;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.util.Log;
import com.remoteyourcam.usb.AppConfig;
import com.remoteyourcam.usb.ptp.Camera.CameraListener;
import com.remoteyourcam.usb.ptp.PtpCamera.State;
---- update 2:
This is the openDevice()
implementation I see in Android 18. As far as I can tell, it handles a general Exception
/**
* Opens the device so it can be used to send and receive
* data using {@link android.hardware.usb.UsbRequest}.
*
* @param device the device to open
* @return a {@link UsbDeviceConnection}, or {@code null} if open failed
*/
public UsbDeviceConnection openDevice(UsbDevice device) {
try {
String deviceName = device.getDeviceName();
ParcelFileDescriptor pfd = mService.openDevice(deviceName);
if (pfd != null) {
UsbDeviceConnection connection = new UsbDeviceConnection(device);
boolean result = connection.open(deviceName, pfd);
pfd.close();
if (result) {
return connection;
}
}
} catch (Exception e) {
Log.e(TAG, "exception in UsbManager.openDevice", e);
}
return null;
}
Upvotes: 2
Views: 2119
Reputation: 58
The same situation I got as you with this source code, I found a trick that avoid crash. Just fix your code
try {
// crash happens in next line:
PtpUsbConnection connection = new PtpUsbConnection(usbManager.openDevice(device), in, out,
device.getVendorId(), device.getProductId());
camera = new EosCamera(connection, listener, new WorkerNotifier(context));
}
catch (IllegalArgumentException e) {
Log.i(TAG, "IllegalArgumentException: camera was switched off? "+ e.getMessage());
e.printStackTrace();
return false;
}
catch (Exception e) {
Log.i(TAG, "Exception: camera was switched off? "+ e.getMessage());
e.printStackTrace();
return false;
}
to
try {
// crash happens in next line:
UsbDeviceConnection udc = usbManager.openDevice(device);
if (udc != null){
PtpUsbConnection connection = new PtpUsbConnection(udc, in, out,
device.getVendorId(), device.getProductId());
camera = new EosCamera(connection, listener, new WorkerNotifier(context));
}
}
catch (IllegalArgumentException e) {
Log.i(TAG, "IllegalArgumentException: camera was switched off? "+ e.getMessage());
e.printStackTrace();
return false;
}
catch (Exception e) {
Log.i(TAG, "Exception: camera was switched off? "+ e.getMessage());
e.printStackTrace();
return false;
}
It works for me!
Upvotes: 0
Reputation: 8395
The Exception is happening in another thread.
You are initializing and dispatching work to another thread asynchronously. Your code only catches exceptions in dispatching the Parcel to the remote Service.
For more information about remote procedure calls in Android you might want to read Deep Dive into Binder.
Upvotes: 2