blob: 46ed041207fbb157a82f96df876d02549494def4 [file] [log] [blame]
Zim3e45d9b2019-08-19 21:14:14 +01001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specic language governing permissions and
14 * limitations under the License.
15 */
16
17// Need to use LOGE_EX.
Zim7e0d3142019-10-17 21:06:12 +010018#define LOG_TAG "FuseDaemonJNI"
Zim3e45d9b2019-08-19 21:14:14 +010019
Zim763428f2021-09-17 11:46:48 +010020#include <nativehelper/scoped_local_ref.h>
shafik8b57cd52019-09-06 10:51:29 +010021#include <nativehelper/scoped_utf_chars.h>
Zim3e45d9b2019-08-19 21:14:14 +010022
23#include <string>
24
shafik8b57cd52019-09-06 10:51:29 +010025#include "FuseDaemon.h"
Narayan Kamathde3fe172020-02-18 12:14:51 +000026#include "MediaProviderWrapper.h"
shafik8b57cd52019-09-06 10:51:29 +010027#include "android-base/logging.h"
Martijn Coenen083eb692020-04-24 09:39:58 +020028#include "android-base/unique_fd.h"
Zim3e45d9b2019-08-19 21:14:14 +010029
30namespace mediaprovider {
31namespace {
32
33constexpr const char* CLASS_NAME = "com/android/providers/media/fuse/FuseDaemon";
34static jclass gFuseDaemonClass;
35
Zim763428f2021-09-17 11:46:48 +010036static std::vector<std::string> get_supported_transcoding_relative_paths(
37 JNIEnv* env, jobjectArray java_supported_transcoding_relative_paths) {
38 ScopedLocalRef<jobjectArray> j_transcoding_relative_paths(
39 env, java_supported_transcoding_relative_paths);
40 std::vector<std::string> transcoding_relative_paths;
41
42 const int transcoding_relative_paths_count =
43 env->GetArrayLength(j_transcoding_relative_paths.get());
44 for (int i = 0; i < transcoding_relative_paths_count; i++) {
45 ScopedLocalRef<jstring> j_ref_relative_path(
46 env, (jstring)env->GetObjectArrayElement(j_transcoding_relative_paths.get(), i));
47 ScopedUtfChars j_utf_relative_path(env, j_ref_relative_path.get());
48 const char* relative_path = j_utf_relative_path.c_str();
49
50 if (relative_path) {
51 transcoding_relative_paths.push_back(relative_path);
52 } else {
53 LOG(ERROR) << "Error reading supported transcoding relative path at index: " << i;
54 }
55 }
56
57 return transcoding_relative_paths;
58}
59
Zimedbe69e2019-12-13 18:49:36 +000060jlong com_android_providers_media_FuseDaemon_new(JNIEnv* env, jobject self,
61 jobject media_provider) {
Narayan Kamath88203dc2019-08-30 17:19:38 +010062 LOG(DEBUG) << "Creating the FUSE daemon...";
Zimedbe69e2019-12-13 18:49:36 +000063 return reinterpret_cast<jlong>(new fuse::FuseDaemon(env, media_provider));
Zim3e45d9b2019-08-19 21:14:14 +010064}
65
Zim763428f2021-09-17 11:46:48 +010066void com_android_providers_media_FuseDaemon_start(
67 JNIEnv* env, jobject self, jlong java_daemon, jint fd, jstring java_path,
68 jobjectArray java_supported_transcoding_relative_paths) {
Narayan Kamath88203dc2019-08-30 17:19:38 +010069 LOG(DEBUG) << "Starting the FUSE daemon...";
Zim3e45d9b2019-08-19 21:14:14 +010070 fuse::FuseDaemon* const daemon = reinterpret_cast<fuse::FuseDaemon*>(java_daemon);
71
Martijn Coenen083eb692020-04-24 09:39:58 +020072 android::base::unique_fd ufd(fd);
73
Zim7c8712d2019-10-03 21:01:26 +010074 ScopedUtfChars utf_chars_path(env, java_path);
75 if (!utf_chars_path.c_str()) {
Zim3e45d9b2019-08-19 21:14:14 +010076 return;
77 }
Zim3e45d9b2019-08-19 21:14:14 +010078
Zim763428f2021-09-17 11:46:48 +010079 const std::vector<std::string>& transcoding_relative_paths =
80 get_supported_transcoding_relative_paths(env,
81 java_supported_transcoding_relative_paths);
82
83 daemon->Start(std::move(ufd), utf_chars_path.c_str(), transcoding_relative_paths);
Zim3e45d9b2019-08-19 21:14:14 +010084}
85
Zimd0435b22020-03-05 13:52:51 +000086bool com_android_providers_media_FuseDaemon_is_started(JNIEnv* env, jobject self,
87 jlong java_daemon) {
88 LOG(DEBUG) << "Checking if FUSE daemon started...";
89 const fuse::FuseDaemon* daemon = reinterpret_cast<fuse::FuseDaemon*>(java_daemon);
90 return daemon->IsStarted();
91}
92
shafik8b57cd52019-09-06 10:51:29 +010093void com_android_providers_media_FuseDaemon_delete(JNIEnv* env, jobject self, jlong java_daemon) {
Narayan Kamath88203dc2019-08-30 17:19:38 +010094 LOG(DEBUG) << "Destroying the FUSE daemon...";
Zim3e45d9b2019-08-19 21:14:14 +010095 fuse::FuseDaemon* const daemon = reinterpret_cast<fuse::FuseDaemon*>(java_daemon);
96 delete daemon;
97}
98
Zimedbe69e2019-12-13 18:49:36 +000099jboolean com_android_providers_media_FuseDaemon_should_open_with_fuse(JNIEnv* env, jobject self,
100 jlong java_daemon,
101 jstring java_path,
102 jboolean for_read, jint fd) {
103 fuse::FuseDaemon* const daemon = reinterpret_cast<fuse::FuseDaemon*>(java_daemon);
104 if (daemon) {
105 ScopedUtfChars utf_chars_path(env, java_path);
106 if (!utf_chars_path.c_str()) {
107 // TODO(b/145741852): Throw exception
108 return JNI_FALSE;
109 }
110
111 return daemon->ShouldOpenWithFuse(fd, for_read, utf_chars_path.c_str());
112 }
113 // TODO(b/145741852): Throw exception
114 return JNI_FALSE;
115}
116
Zima76c3492020-02-19 01:23:26 +0000117void com_android_providers_media_FuseDaemon_invalidate_fuse_dentry_cache(JNIEnv* env, jobject self,
118 jlong java_daemon,
119 jstring java_path) {
120 fuse::FuseDaemon* const daemon = reinterpret_cast<fuse::FuseDaemon*>(java_daemon);
121 if (daemon) {
122 ScopedUtfChars utf_chars_path(env, java_path);
123 if (!utf_chars_path.c_str()) {
124 // TODO(b/145741152): Throw exception
125 return;
126 }
127
Colin Cross915ad6a2020-04-03 18:19:07 -0700128 CHECK(pthread_getspecific(fuse::MediaProviderWrapper::gJniEnvKey) == nullptr);
Zima76c3492020-02-19 01:23:26 +0000129 daemon->InvalidateFuseDentryCache(utf_chars_path.c_str());
130 }
131 // TODO(b/145741152): Throw exception
132}
133
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000134jstring com_android_providers_media_FuseDaemon_get_original_media_format_file_path(
135 JNIEnv* env, jobject self, jlong java_daemon, jint fd) {
136 fuse::FuseDaemon* const daemon = reinterpret_cast<fuse::FuseDaemon*>(java_daemon);
137 const std::string path = daemon->GetOriginalMediaFormatFilePath(fd);
138 return env->NewStringUTF(path.c_str());
139}
140
141void com_android_providers_media_FuseDaemon_initialize_device_id(JNIEnv* env, jobject self,
142 jlong java_daemon,
143 jstring java_path) {
144 fuse::FuseDaemon* const daemon = reinterpret_cast<fuse::FuseDaemon*>(java_daemon);
145 ScopedUtfChars utf_chars_path(env, java_path);
146 if (!utf_chars_path.c_str()) {
147 LOG(WARNING) << "Couldn't initialise FUSE device id";
148 return;
149 }
150 daemon->InitializeDeviceId(utf_chars_path.c_str());
151}
152
Zimc0e65bd2020-03-09 15:22:59 +0000153bool com_android_providers_media_FuseDaemon_is_fuse_thread(JNIEnv* env, jclass clazz) {
Zimc0e65bd2020-03-09 15:22:59 +0000154 return pthread_getspecific(fuse::MediaProviderWrapper::gJniEnvKey) != nullptr;
155}
156
Zim3e45d9b2019-08-19 21:14:14 +0100157const JNINativeMethod methods[] = {
Zim7c8712d2019-10-03 21:01:26 +0100158 {"native_new", "(Lcom/android/providers/media/MediaProvider;)J",
159 reinterpret_cast<void*>(com_android_providers_media_FuseDaemon_new)},
Zim763428f2021-09-17 11:46:48 +0100160 {"native_start", "(JILjava/lang/String;[Ljava/lang/String;)V",
Zim7c8712d2019-10-03 21:01:26 +0100161 reinterpret_cast<void*>(com_android_providers_media_FuseDaemon_start)},
Zim7c8712d2019-10-03 21:01:26 +0100162 {"native_delete", "(J)V",
Zimedbe69e2019-12-13 18:49:36 +0000163 reinterpret_cast<void*>(com_android_providers_media_FuseDaemon_delete)},
164 {"native_should_open_with_fuse", "(JLjava/lang/String;ZI)Z",
Zima76c3492020-02-19 01:23:26 +0000165 reinterpret_cast<void*>(com_android_providers_media_FuseDaemon_should_open_with_fuse)},
Zimc0e65bd2020-03-09 15:22:59 +0000166 {"native_is_fuse_thread", "()Z",
167 reinterpret_cast<void*>(com_android_providers_media_FuseDaemon_is_fuse_thread)},
Zimd0435b22020-03-05 13:52:51 +0000168 {"native_is_started", "(J)Z",
169 reinterpret_cast<void*>(com_android_providers_media_FuseDaemon_is_started)},
Zima76c3492020-02-19 01:23:26 +0000170 {"native_invalidate_fuse_dentry_cache", "(JLjava/lang/String;)V",
171 reinterpret_cast<void*>(
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000172 com_android_providers_media_FuseDaemon_invalidate_fuse_dentry_cache)},
173 {"native_get_original_media_format_file_path", "(JI)Ljava/lang/String;",
174 reinterpret_cast<void*>(
175 com_android_providers_media_FuseDaemon_get_original_media_format_file_path)},
176 {"native_initialize_device_id", "(JLjava/lang/String;)V",
177 reinterpret_cast<void*>(com_android_providers_media_FuseDaemon_initialize_device_id)}};
Zim3e45d9b2019-08-19 21:14:14 +0100178} // namespace
179
Narayan Kamathde3fe172020-02-18 12:14:51 +0000180void register_android_providers_media_FuseDaemon(JavaVM* vm, JNIEnv* env) {
Zim3e45d9b2019-08-19 21:14:14 +0100181 gFuseDaemonClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass(CLASS_NAME)));
Narayan Kamath88203dc2019-08-30 17:19:38 +0100182
183 if (gFuseDaemonClass == nullptr) {
184 LOG(FATAL) << "Unable to find class : " << CLASS_NAME;
185 }
186
shafik8b57cd52019-09-06 10:51:29 +0100187 if (env->RegisterNatives(gFuseDaemonClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
Narayan Kamath88203dc2019-08-30 17:19:38 +0100188 LOG(FATAL) << "Unable to register native methods";
189 }
Narayan Kamathde3fe172020-02-18 12:14:51 +0000190
191 fuse::MediaProviderWrapper::OneTimeInit(vm);
Zim3e45d9b2019-08-19 21:14:14 +0100192}
193} // namespace mediaprovider