f9c5c2574d
MtpStorageManager keeps track of file information and send notifications for new files. MtpDatabase now uses this instead of MediaProvider for getting object information, although some operations are still reflected into MP. Since MtpStorageManager handles storage ids, remove that field from StorageVolume and VolumeInfo. Clean up a lot of the jni code for MtpDatabase. Bug: 63143623 Test: Test every MtpOperation in a variety of situations on Linux and Windows. Also use the shell to manipulate files. Verify that the cache is consistent throughout, and the operations behave as expected. Verify files created by the shell appear. Test: adb shell am instrument -w android.mtp /android.support.test.runner.AndroidJUnitRunner Change-Id: Id4ea810047b0c323399cd833047733e5daafb30a
267 lines
9.5 KiB
C++
267 lines
9.5 KiB
C++
/*
|
|
* Copyright (C) 2010 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.
|
|
*/
|
|
|
|
#define LOG_TAG "MtpServerJNI"
|
|
#include "utils/Log.h"
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <limits.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <utils/threads.h>
|
|
|
|
#include "jni.h"
|
|
#include <nativehelper/JNIHelp.h>
|
|
#include "android_runtime/AndroidRuntime.h"
|
|
#include "private/android_filesystem_config.h"
|
|
|
|
#include "MtpServer.h"
|
|
#include "MtpStorage.h"
|
|
|
|
using namespace android;
|
|
|
|
// MtpServer fields
|
|
static jfieldID field_MtpServer_nativeContext;
|
|
|
|
// MtpStorage fields
|
|
static jfieldID field_MtpStorage_storageId;
|
|
static jfieldID field_MtpStorage_path;
|
|
static jfieldID field_MtpStorage_description;
|
|
static jfieldID field_MtpStorage_removable;
|
|
static jfieldID field_MtpStorage_maxFileSize;
|
|
|
|
static Mutex sMutex;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// in android_mtp_MtpDatabase.cpp
|
|
extern IMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
|
|
|
|
static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) {
|
|
return (MtpServer*)env->GetLongField(thiz, field_MtpServer_nativeContext);
|
|
}
|
|
|
|
static void android_mtp_configure(JNIEnv *, jobject, jboolean usePtp) {
|
|
MtpServer::configure(usePtp);
|
|
}
|
|
|
|
static void
|
|
android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp,
|
|
jstring deviceInfoManufacturer,
|
|
jstring deviceInfoModel,
|
|
jstring deviceInfoDeviceVersion,
|
|
jstring deviceInfoSerialNumber)
|
|
{
|
|
const char *deviceInfoManufacturerStr = env->GetStringUTFChars(deviceInfoManufacturer, NULL);
|
|
const char *deviceInfoModelStr = env->GetStringUTFChars(deviceInfoModel, NULL);
|
|
const char *deviceInfoDeviceVersionStr = env->GetStringUTFChars(deviceInfoDeviceVersion, NULL);
|
|
const char *deviceInfoSerialNumberStr = env->GetStringUTFChars(deviceInfoSerialNumber, NULL);
|
|
MtpServer* server = new MtpServer(getMtpDatabase(env, javaDatabase),
|
|
usePtp,
|
|
MtpString((deviceInfoManufacturerStr != NULL) ? deviceInfoManufacturerStr : ""),
|
|
MtpString((deviceInfoModelStr != NULL) ? deviceInfoModelStr : ""),
|
|
MtpString((deviceInfoDeviceVersionStr != NULL) ? deviceInfoDeviceVersionStr : ""),
|
|
MtpString((deviceInfoSerialNumberStr != NULL) ? deviceInfoSerialNumberStr : ""));
|
|
if (deviceInfoManufacturerStr != NULL) {
|
|
env->ReleaseStringUTFChars(deviceInfoManufacturer, deviceInfoManufacturerStr);
|
|
}
|
|
if (deviceInfoModelStr != NULL) {
|
|
env->ReleaseStringUTFChars(deviceInfoModel, deviceInfoModelStr);
|
|
}
|
|
if (deviceInfoDeviceVersionStr != NULL) {
|
|
env->ReleaseStringUTFChars(deviceInfoDeviceVersion, deviceInfoDeviceVersionStr);
|
|
}
|
|
if (deviceInfoSerialNumberStr != NULL) {
|
|
env->ReleaseStringUTFChars(deviceInfoSerialNumber, deviceInfoSerialNumberStr);
|
|
}
|
|
env->SetLongField(thiz, field_MtpServer_nativeContext, (jlong)server);
|
|
}
|
|
|
|
static void
|
|
android_mtp_MtpServer_run(JNIEnv *env, jobject thiz)
|
|
{
|
|
MtpServer* server = getMtpServer(env, thiz);
|
|
if (server)
|
|
server->run();
|
|
else
|
|
ALOGE("server is null in run");
|
|
}
|
|
|
|
static void
|
|
android_mtp_MtpServer_cleanup(JNIEnv *env, jobject thiz)
|
|
{
|
|
Mutex::Autolock autoLock(sMutex);
|
|
|
|
MtpServer* server = getMtpServer(env, thiz);
|
|
if (server) {
|
|
delete server;
|
|
env->SetLongField(thiz, field_MtpServer_nativeContext, 0);
|
|
} else {
|
|
ALOGE("server is null in cleanup");
|
|
}
|
|
}
|
|
|
|
static void
|
|
android_mtp_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
|
|
{
|
|
Mutex::Autolock autoLock(sMutex);
|
|
|
|
MtpServer* server = getMtpServer(env, thiz);
|
|
if (server)
|
|
server->sendObjectAdded(handle);
|
|
else
|
|
ALOGE("server is null in send_object_added");
|
|
}
|
|
|
|
static void
|
|
android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
|
|
{
|
|
Mutex::Autolock autoLock(sMutex);
|
|
|
|
MtpServer* server = getMtpServer(env, thiz);
|
|
if (server)
|
|
server->sendObjectRemoved(handle);
|
|
else
|
|
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)
|
|
{
|
|
Mutex::Autolock autoLock(sMutex);
|
|
|
|
MtpServer* server = getMtpServer(env, thiz);
|
|
if (server) {
|
|
jint storageID = env->GetIntField(jstorage, field_MtpStorage_storageId);
|
|
jstring path = (jstring)env->GetObjectField(jstorage, field_MtpStorage_path);
|
|
jstring description = (jstring)env->GetObjectField(jstorage, field_MtpStorage_description);
|
|
jboolean removable = env->GetBooleanField(jstorage, field_MtpStorage_removable);
|
|
jlong maxFileSize = env->GetLongField(jstorage, field_MtpStorage_maxFileSize);
|
|
|
|
const char *pathStr = env->GetStringUTFChars(path, NULL);
|
|
if (pathStr != NULL) {
|
|
const char *descriptionStr = env->GetStringUTFChars(description, NULL);
|
|
if (descriptionStr != NULL) {
|
|
MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr,
|
|
removable, maxFileSize);
|
|
server->addStorage(storage);
|
|
env->ReleaseStringUTFChars(path, pathStr);
|
|
env->ReleaseStringUTFChars(description, descriptionStr);
|
|
} else {
|
|
env->ReleaseStringUTFChars(path, pathStr);
|
|
}
|
|
}
|
|
} else {
|
|
ALOGE("server is null in add_storage");
|
|
}
|
|
}
|
|
|
|
static void
|
|
android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId)
|
|
{
|
|
Mutex::Autolock autoLock(sMutex);
|
|
|
|
MtpServer* server = getMtpServer(env, thiz);
|
|
if (server) {
|
|
MtpStorage* storage = server->getStorage(storageId);
|
|
if (storage) {
|
|
server->removeStorage(storage);
|
|
delete storage;
|
|
}
|
|
} else
|
|
ALOGE("server is null in remove_storage");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
static const JNINativeMethod gMethods[] = {
|
|
{"native_configure", "(Z)V", (void *)android_mtp_configure},
|
|
{"native_setup", "(Landroid/mtp/MtpDatabase;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
|
|
(void *)android_mtp_MtpServer_setup},
|
|
{"native_run", "()V", (void *)android_mtp_MtpServer_run},
|
|
{"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},
|
|
};
|
|
|
|
int register_android_mtp_MtpServer(JNIEnv *env)
|
|
{
|
|
jclass clazz;
|
|
|
|
clazz = env->FindClass("android/mtp/MtpStorage");
|
|
if (clazz == NULL) {
|
|
ALOGE("Can't find android/mtp/MtpStorage");
|
|
return -1;
|
|
}
|
|
field_MtpStorage_storageId = env->GetFieldID(clazz, "mStorageId", "I");
|
|
if (field_MtpStorage_storageId == NULL) {
|
|
ALOGE("Can't find MtpStorage.mStorageId");
|
|
return -1;
|
|
}
|
|
field_MtpStorage_path = env->GetFieldID(clazz, "mPath", "Ljava/lang/String;");
|
|
if (field_MtpStorage_path == NULL) {
|
|
ALOGE("Can't find MtpStorage.mPath");
|
|
return -1;
|
|
}
|
|
field_MtpStorage_description = env->GetFieldID(clazz, "mDescription", "Ljava/lang/String;");
|
|
if (field_MtpStorage_description == NULL) {
|
|
ALOGE("Can't find MtpStorage.mDescription");
|
|
return -1;
|
|
}
|
|
field_MtpStorage_removable = env->GetFieldID(clazz, "mRemovable", "Z");
|
|
if (field_MtpStorage_removable == NULL) {
|
|
ALOGE("Can't find MtpStorage.mRemovable");
|
|
return -1;
|
|
}
|
|
field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
|
|
if (field_MtpStorage_maxFileSize == NULL) {
|
|
ALOGE("Can't find MtpStorage.mMaxFileSize");
|
|
return -1;
|
|
}
|
|
|
|
clazz = env->FindClass("android/mtp/MtpServer");
|
|
if (clazz == NULL) {
|
|
ALOGE("Can't find android/mtp/MtpServer");
|
|
return -1;
|
|
}
|
|
field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "J");
|
|
if (field_MtpServer_nativeContext == NULL) {
|
|
ALOGE("Can't find MtpServer.mNativeContext");
|
|
return -1;
|
|
}
|
|
|
|
return AndroidRuntime::registerNativeMethods(env,
|
|
"android/mtp/MtpServer", gMethods, NELEM(gMethods));
|
|
}
|