Warning, /graphics/krita/3rdparty/ext_qt/0022-Android-Properly-close-the-File-Descriptor.patch is written in an unsupported language. File is not indexed.
0001 From b6be4ece264a95314eb04f88dfcefe7359adba62 Mon Sep 17 00:00:00 2001 0002 From: Sharaf Zaman <sharafzaz121@gmail.com> 0003 Date: Mon, 21 Sep 2020 11:06:37 +0000 0004 Subject: [PATCH 22/46] Android: Properly close the File Descriptor 0005 0006 In some we are not supposed to detach the file 0007 descriptor from the original object that created it. 0008 With this patch, we save the don't detach, but 0009 save the ParcelFileDescriptor in a Map and close it 0010 when we receive close() from C++. 0011 0012 Direct effect of this can be seen in Krita, where some 0013 content providers would not allow writing to some detached 0014 FD. 0015 --- 0016 .../org/qtproject/qt5/android/QtNative.java | 29 +++++++++++++++++-- 0017 .../android/androidcontentfileengine.cpp | 17 +++++++++-- 0018 .../android/androidcontentfileengine.h | 6 ++++ 0019 3 files changed, 47 insertions(+), 5 deletions(-) 0020 0021 diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java 0022 index b838720213..5e9749f264 100644 0023 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java 0024 +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java 0025 @@ -43,6 +43,7 @@ package org.qtproject.qt5.android; 0026 import java.io.File; 0027 import java.io.FileNotFoundException; 0028 import java.util.ArrayList; 0029 +import java.util.HashMap; 0030 import java.util.concurrent.Semaphore; 0031 import java.io.IOException; 0032 0033 @@ -112,6 +113,9 @@ public class QtNative 0034 private static boolean m_usePrimaryClip = false; 0035 public static QtThread m_qtThread = new QtThread(); 0036 private static Method m_addItemMethod = null; 0037 + 0038 + private static HashMap<Integer, ParcelFileDescriptor> m_parcelFileDescriptors = new HashMap<Integer, ParcelFileDescriptor>(); 0039 + 0040 private static final Runnable runPendingCppRunnablesRunnable = new Runnable() { 0041 @Override 0042 public void run() { 0043 @@ -177,8 +181,9 @@ public class QtNative 0044 if (!openMode.equals("r")) 0045 isRightPermission = permissions.get(i).isWritePermission(); 0046 0047 - if (iterUri.getPath().equals(uriStr) && isRightPermission) 0048 + if (iterUri.getPath().equals(uriStr) && isRightPermission) { 0049 return iterUri; 0050 + } 0051 } 0052 0053 return null; 0054 @@ -235,7 +240,8 @@ public class QtNative 0055 try { 0056 ContentResolver resolver = context.getContentResolver(); 0057 ParcelFileDescriptor fdDesc = resolver.openFileDescriptor(uri, openMode); 0058 - return fdDesc.detachFd(); 0059 + m_parcelFileDescriptors.put(fdDesc.getFd(), fdDesc); 0060 + return fdDesc.getFd(); 0061 } catch (FileNotFoundException e) { 0062 return error; 0063 } catch (IllegalArgumentException e) { 0064 @@ -244,6 +250,23 @@ public class QtNative 0065 } 0066 } 0067 0068 + public static boolean closeFd(int fd) 0069 + { 0070 + ParcelFileDescriptor pfd = m_parcelFileDescriptors.get(fd); 0071 + if (pfd == null) { 0072 + Log.wtf(QtTAG, "File descriptor doesn't exist in cache"); 0073 + return false; 0074 + } 0075 + 0076 + try { 0077 + pfd.close(); 0078 + return true; 0079 + } catch (IOException e) { 0080 + Log.e(QtTAG, "closeFd(): Failed to close the FD", e); 0081 + return false; 0082 + } 0083 + } 0084 + 0085 public static long getSize(Context context, String contentUrl) 0086 { 0087 Uri uri = getUriWithValidPermission(context, contentUrl, "r"); 0088 @@ -304,7 +327,7 @@ public class QtNative 0089 { 0090 Uri uri = getUriWithValidPermission(context, contentUrl, "r"); 0091 if (uri == null) { 0092 - Log.e(QtTAG, "getFileNameFromUri(): No permissions to open Uri"); 0093 + Log.e(QtTAG, "getFileNameFromUri(): No permissions to open Uri:" + contentUrl); 0094 return null; 0095 } 0096 0097 diff --git a/src/plugins/platforms/android/androidcontentfileengine.cpp b/src/plugins/platforms/android/androidcontentfileengine.cpp 0098 index c15352d60e..2c11f5f14a 100644 0099 --- a/src/plugins/platforms/android/androidcontentfileengine.cpp 0100 +++ b/src/plugins/platforms/android/androidcontentfileengine.cpp 0101 @@ -45,7 +45,7 @@ 0102 #include <QDebug> 0103 0104 AndroidContentFileEngine::AndroidContentFileEngine(const QString &f) 0105 - : m_file(f), m_resolvedName(QString()) 0106 + : m_fd(-1), m_file(f), m_resolvedName(QString()) 0107 { 0108 setFileName(f); 0109 setResolvedFileName(f); 0110 @@ -77,7 +77,15 @@ bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode) 0111 return false; 0112 } 0113 0114 - return QFSFileEngine::open(openMode, fd, QFile::AutoCloseHandle); 0115 + setFileDescriptor(fd); 0116 + return QFSFileEngine::open(openMode, m_fd, QFile::AutoCloseHandle); 0117 +} 0118 + 0119 +bool AndroidContentFileEngine::close() 0120 +{ 0121 + return QJNIObjectPrivate::callStaticMethod<jboolean>( 0122 + "org/qtproject/qt5/android/QtNative", "closeFd", 0123 + "(I)Z", m_fd); 0124 } 0125 0126 qint64 AndroidContentFileEngine::size() const 0127 @@ -141,6 +149,11 @@ void AndroidContentFileEngine::setResolvedFileName(const QString& uri) 0128 } 0129 } 0130 0131 +void AndroidContentFileEngine::setFileDescriptor(const int fd) 0132 +{ 0133 + m_fd = fd; 0134 +} 0135 + 0136 0137 AndroidContentFileEngineHandler::AndroidContentFileEngineHandler() = default; 0138 AndroidContentFileEngineHandler::~AndroidContentFileEngineHandler() = default; 0139 diff --git a/src/plugins/platforms/android/androidcontentfileengine.h b/src/plugins/platforms/android/androidcontentfileengine.h 0140 index bb97bd6975..abf969ba20 100644 0141 --- a/src/plugins/platforms/android/androidcontentfileengine.h 0142 +++ b/src/plugins/platforms/android/androidcontentfileengine.h 0143 @@ -47,13 +47,19 @@ class AndroidContentFileEngine : public QFSFileEngine 0144 public: 0145 AndroidContentFileEngine(const QString &fileName); 0146 bool open(QIODevice::OpenMode openMode) override; 0147 + bool close() override; 0148 qint64 size() const override; 0149 FileFlags fileFlags(FileFlags type = FileInfoAll) const override; 0150 QString fileName(FileName file = DefaultName) const override; 0151 0152 /// Resolves the URI to the actual filename 0153 void setResolvedFileName(const QString& uri); 0154 + 0155 +private: 0156 + void setFileDescriptor(const int fd); 0157 + 0158 private: 0159 + int m_fd; 0160 QString m_file; 0161 QString m_resolvedName; 0162 }; 0163 -- 0164 2.33.0 0165