MTP: Add support for battery level device property
Bug: 7342482 Change-Id: I810e55fe9695e2206816f57334ad14f65e9c641d
This commit is contained in:
@ -16,15 +16,19 @@
|
||||
|
||||
package android.mtp;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.ContentValues;
|
||||
import android.content.IContentProvider;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.media.MediaScanner;
|
||||
import android.net.Uri;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.MediaStore.Audio;
|
||||
@ -113,11 +117,35 @@ public class MtpDatabase {
|
||||
+ Files.FileColumns.PARENT + "=?";
|
||||
|
||||
private final MediaScanner mMediaScanner;
|
||||
private MtpServer mServer;
|
||||
|
||||
// read from native code
|
||||
private int mBatteryLevel;
|
||||
private int mBatteryScale;
|
||||
|
||||
static {
|
||||
System.loadLibrary("media_jni");
|
||||
}
|
||||
|
||||
private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
|
||||
mBatteryScale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
|
||||
int newLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
|
||||
if (newLevel != mBatteryLevel) {
|
||||
mBatteryLevel = newLevel;
|
||||
if (mServer != null) {
|
||||
// send device property changed event
|
||||
mServer.sendDevicePropertyChanged(
|
||||
MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public MtpDatabase(Context context, String volumeName, String storagePath,
|
||||
String[] subDirectories) {
|
||||
native_setup();
|
||||
@ -171,6 +199,18 @@ public class MtpDatabase {
|
||||
initDeviceProperties(context);
|
||||
}
|
||||
|
||||
public void setServer(MtpServer server) {
|
||||
mServer = server;
|
||||
|
||||
// register for battery notifications when we are connected
|
||||
if (server != null) {
|
||||
mContext.registerReceiver(mBatteryReceiver,
|
||||
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
} else {
|
||||
mContext.unregisterReceiver(mBatteryReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
@ -663,6 +703,7 @@ public class MtpDatabase {
|
||||
MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
|
||||
MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
|
||||
MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
|
||||
MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL,
|
||||
};
|
||||
}
|
||||
|
||||
@ -819,6 +860,8 @@ public class MtpDatabase {
|
||||
outStringValue[imageSize.length()] = 0;
|
||||
return MtpConstants.RESPONSE_OK;
|
||||
|
||||
// DEVICE_PROPERTY_BATTERY_LEVEL is implemented in the JNI code
|
||||
|
||||
default:
|
||||
return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ public class MtpServer implements Runnable {
|
||||
|
||||
public MtpServer(MtpDatabase database, boolean usePtp) {
|
||||
native_setup(database, usePtp);
|
||||
database.setServer(this);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
@ -51,6 +52,10 @@ public class MtpServer implements Runnable {
|
||||
native_send_object_removed(handle);
|
||||
}
|
||||
|
||||
public void sendDevicePropertyChanged(int property) {
|
||||
native_send_device_property_changed(property);
|
||||
}
|
||||
|
||||
public void addStorage(MtpStorage storage) {
|
||||
native_add_storage(storage);
|
||||
}
|
||||
@ -64,6 +69,7 @@ public class MtpServer implements Runnable {
|
||||
private native final void native_cleanup();
|
||||
private native final void native_send_object_added(int handle);
|
||||
private native final void native_send_object_removed(int handle);
|
||||
private native final void native_send_device_property_changed(int property);
|
||||
private native final void native_add_storage(MtpStorage storage);
|
||||
private native final void native_remove_storage(int storageId);
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ static jmethodID method_sessionStarted;
|
||||
static jmethodID method_sessionEnded;
|
||||
|
||||
static jfieldID field_context;
|
||||
static jfieldID field_batteryLevel;
|
||||
static jfieldID field_batteryScale;
|
||||
|
||||
// MtpPropertyList fields
|
||||
static jfieldID field_mCount;
|
||||
@ -527,68 +529,75 @@ MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
|
||||
|
||||
MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
|
||||
MtpDataPacket& packet) {
|
||||
int type;
|
||||
|
||||
if (!getDevicePropertyInfo(property, type))
|
||||
return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
|
||||
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
|
||||
(jint)property, mLongBuffer, mStringBuffer);
|
||||
if (result != MTP_RESPONSE_OK) {
|
||||
|
||||
if (property == MTP_DEVICE_PROPERTY_BATTERY_LEVEL) {
|
||||
// special case - implemented here instead of Java
|
||||
packet.putUInt8((uint8_t)env->GetIntField(mDatabase, field_batteryLevel));
|
||||
return MTP_RESPONSE_OK;
|
||||
} else {
|
||||
int type;
|
||||
|
||||
if (!getDevicePropertyInfo(property, type))
|
||||
return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
|
||||
|
||||
jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
|
||||
(jint)property, mLongBuffer, mStringBuffer);
|
||||
if (result != MTP_RESPONSE_OK) {
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
return result;
|
||||
}
|
||||
|
||||
jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
|
||||
jlong longValue = longValues[0];
|
||||
env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
|
||||
|
||||
switch (type) {
|
||||
case MTP_TYPE_INT8:
|
||||
packet.putInt8(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT8:
|
||||
packet.putUInt8(longValue);
|
||||
break;
|
||||
case MTP_TYPE_INT16:
|
||||
packet.putInt16(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT16:
|
||||
packet.putUInt16(longValue);
|
||||
break;
|
||||
case MTP_TYPE_INT32:
|
||||
packet.putInt32(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT32:
|
||||
packet.putUInt32(longValue);
|
||||
break;
|
||||
case MTP_TYPE_INT64:
|
||||
packet.putInt64(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT64:
|
||||
packet.putUInt64(longValue);
|
||||
break;
|
||||
case MTP_TYPE_INT128:
|
||||
packet.putInt128(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT128:
|
||||
packet.putInt128(longValue);
|
||||
break;
|
||||
case MTP_TYPE_STR:
|
||||
{
|
||||
jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
|
||||
packet.putString(str);
|
||||
env->ReleaseCharArrayElements(mStringBuffer, str, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ALOGE("unsupported type in getDevicePropertyValue\n");
|
||||
return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
|
||||
}
|
||||
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
return result;
|
||||
return MTP_RESPONSE_OK;
|
||||
}
|
||||
|
||||
jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
|
||||
jlong longValue = longValues[0];
|
||||
env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
|
||||
|
||||
switch (type) {
|
||||
case MTP_TYPE_INT8:
|
||||
packet.putInt8(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT8:
|
||||
packet.putUInt8(longValue);
|
||||
break;
|
||||
case MTP_TYPE_INT16:
|
||||
packet.putInt16(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT16:
|
||||
packet.putUInt16(longValue);
|
||||
break;
|
||||
case MTP_TYPE_INT32:
|
||||
packet.putInt32(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT32:
|
||||
packet.putUInt32(longValue);
|
||||
break;
|
||||
case MTP_TYPE_INT64:
|
||||
packet.putInt64(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT64:
|
||||
packet.putUInt64(longValue);
|
||||
break;
|
||||
case MTP_TYPE_INT128:
|
||||
packet.putInt128(longValue);
|
||||
break;
|
||||
case MTP_TYPE_UINT128:
|
||||
packet.putInt128(longValue);
|
||||
break;
|
||||
case MTP_TYPE_STR:
|
||||
{
|
||||
jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
|
||||
packet.putString(str);
|
||||
env->ReleaseCharArrayElements(mStringBuffer, str, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ALOGE("unsupported type in getDevicePropertyValue\n");
|
||||
return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
|
||||
}
|
||||
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
return MTP_RESPONSE_OK;
|
||||
}
|
||||
|
||||
MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
|
||||
@ -923,6 +932,7 @@ static const PropertyTableEntry kDevicePropertyTable[] = {
|
||||
{ MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
|
||||
{ MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
|
||||
{ MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
|
||||
{ MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT8 },
|
||||
};
|
||||
|
||||
bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
|
||||
@ -1046,7 +1056,7 @@ MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
|
||||
case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
|
||||
writable = true;
|
||||
// fall through
|
||||
case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
|
||||
case MTP_DEVICE_PROPERTY_IMAGE_SIZE: {
|
||||
result = new MtpProperty(property, MTP_TYPE_STR, writable);
|
||||
|
||||
// get current value
|
||||
@ -1063,6 +1073,12 @@ MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
|
||||
ALOGE("unable to read device property, response: %04X", ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MTP_DEVICE_PROPERTY_BATTERY_LEVEL:
|
||||
result = new MtpProperty(property, MTP_TYPE_UINT8);
|
||||
result->setFormRange(0, env->GetIntField(mDatabase, field_batteryScale), 1);
|
||||
result->mCurrentValue.u.u8 = (uint8_t)env->GetIntField(mDatabase, field_batteryLevel);
|
||||
break;
|
||||
}
|
||||
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
@ -1234,6 +1250,16 @@ int register_android_mtp_MtpDatabase(JNIEnv *env)
|
||||
ALOGE("Can't find MtpDatabase.mNativeContext");
|
||||
return -1;
|
||||
}
|
||||
field_batteryLevel = env->GetFieldID(clazz, "mBatteryLevel", "I");
|
||||
if (field_batteryLevel == NULL) {
|
||||
ALOGE("Can't find MtpDatabase.mBatteryLevel");
|
||||
return -1;
|
||||
}
|
||||
field_batteryScale = env->GetFieldID(clazz, "mBatteryScale", "I");
|
||||
if (field_batteryScale == NULL) {
|
||||
ALOGE("Can't find MtpDatabase.mBatteryScale");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// now set up fields for MtpPropertyList class
|
||||
clazz = env->FindClass("android/mtp/MtpPropertyList");
|
||||
|
@ -117,6 +117,18 @@ android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle
|
||||
ALOGE("server is null in send_object_removed");
|
||||
}
|
||||
|
||||
static void
|
||||
android_mtp_MtpServer_send_device_property_changed(JNIEnv *env, jobject thiz, jint property)
|
||||
{
|
||||
Mutex::Autolock autoLock(sMutex);
|
||||
|
||||
MtpServer* server = getMtpServer(env, thiz);
|
||||
if (server)
|
||||
server->sendDevicePropertyChanged(property);
|
||||
else
|
||||
ALOGE("server is null in send_object_removed");
|
||||
}
|
||||
|
||||
static void
|
||||
android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
|
||||
{
|
||||
@ -174,6 +186,8 @@ static JNINativeMethod gMethods[] = {
|
||||
{"native_cleanup", "()V", (void *)android_mtp_MtpServer_cleanup},
|
||||
{"native_send_object_added", "(I)V", (void *)android_mtp_MtpServer_send_object_added},
|
||||
{"native_send_object_removed", "(I)V", (void *)android_mtp_MtpServer_send_object_removed},
|
||||
{"native_send_device_property_changed", "(I)V",
|
||||
(void *)android_mtp_MtpServer_send_device_property_changed},
|
||||
{"native_add_storage", "(Landroid/mtp/MtpStorage;)V",
|
||||
(void *)android_mtp_MtpServer_add_storage},
|
||||
{"native_remove_storage", "(I)V", (void *)android_mtp_MtpServer_remove_storage},
|
||||
|
Reference in New Issue
Block a user