Xamarin-Android - динамически загружать встроенную библиотеку C, встроенную в сборку .NET - PullRequest
0 голосов
/ 04 ноября 2019

Я пытаюсь динамически загрузить собственную встроенную библиотеку C, которая встроена в библиотеку .NET во время сборки и используется в приложении Xamarin-Android.

Процесс, который я хочу выполнить:

  • Я собираю библиотеку .NET и встраиваю в нее библиотеку C. - Работает
  • Я создаю приложение Xamarin для Android, которое использует мою библиотеку .NET. - Работает
  • . Во время выполнения .NET извлекает библиотеку C из папки files моего приложения. - Работает
  • После извлечения библиотеки C я динамически загружаю ее, используя dlopen. ,- Сбой

Как указано выше, последние шаги завершаются неудачно с сообщением такого типа:

library /data/user/0/com.companyname.namespace/files/mylibrary.so" needed or dlopened by "(unknown)" is not
accessible for the namespace: [name="(anonymous)", ld_library_paths="", 
default_library_paths="/data/app/com.companyname.namespace-O7aSwdg3bwneAoiHpkw1zg==/lib/arm64:/data/app/com.companyname.namespace-O7aSwdg3bwneAoiHpkw1zg==/base.apk!/lib/arm64-v8a", permitted_paths=""]

Теперь я знаю, что из API 24 политика Android изменилась назапретить разработчикам загружать собственные библиотеки, которые не являются частью NDK (см. этот выпуск changelog ).

Однако, согласно этого блога и этого другогоблог кажется, что они больше пытаются отговорить людей от этого, чем от того, чтобы полностью предотвратить это, и поэтому то, что я пытаюсь добиться звучания, возможно.

Я попробовал то, что предлагает первый блог, разницу междуэто и мой случай, когда я использую C # для вызова android_create_namespace и android_dlopen_ext, а также для создания структур. Вызов android_create_namespace, кажется, работает, когда я получаю адрес, однако вызов android_dlopen_ext возвращает NULL, что бы я ни пытался.

См. Код ниже, AndroidDlopen - основная функция, в которой возникает проблема:

internal static class AndroidNative
    {
        private const string LibName = "libandroid";

        private const int ANDROID_DLEXT_USE_NAMESPACE = 0x200;
        private const int RTLD_LOCAL = 0x0;
        private const int RTLD_NOW = 0x00002;
        private const int RTLD_LAZY = 0x00001;

        [DllImport(LibName)]
        public static extern int __android_log_print(int prio, string tag, string fmt);

        [StructLayout(LayoutKind.Sequential)]
        public struct AndroidDlextinfo
        {
            public ulong Flags;
            public int LibraryFd;
            public long LibraryFdOffset;
            public IntPtr LibraryNamespace;
            public int RelroFd;
            public IntPtr ReservedAddr;
            public uint ReservedSize;
        }

        public enum AndroidNamespaceType : ulong
        {
            Regular = 0,
            Isolated = 1,
            Shared = 2,
            GreyListEnabled = 0x08000000, 
            SharedIsolated = Shared | Isolated
        };

        [DllImport(LibName, EntryPoint = "android_create_namespace", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr AndroidCreateNamespace(string name, string ldLibraryPath, string defaultLibraryPath,
                                                           AndroidNamespaceType type, string permittedWhenIsolatedPath,
                                                           IntPtr parent);

        [DllImport(LibName, EntryPoint = "android_dlopen_ext", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr androidDlopenExt(string filename, int flags, AndroidDlextinfo info);

        public static IntPtr AndroidDlopen(string name)
        {
            string chirpAssemblyFolder = ChirpDataHandler.ChirpUserFolder;

            IntPtr chirpNamespace = AndroidCreateNamespace("trustme", "/system/lib64/", "/system/lib64/",
                                               AndroidNamespaceType.SharedIsolated, "/system/:/data/:/vendor/",
                                               IntPtr.Zero);

            AndroidDlextinfo androidDlextinfo = new AndroidDlextinfo
            {
                Flags = ANDROID_DLEXT_USE_NAMESPACE,
                LibraryNamespace = chirpNamespace,
            };

            IntPtr handle = androidDlopenExt(Path.Combine(chirpAssemblyFolder, name), RTLD_NOW, androidDlextinfo);
            return handle;
        }
    }

Я знаю, что это было бы возможно, если бы я включил библиотеку C в сборку приложения для Android, но в моем случае это не вариант.

Так что я бы хотелхотелось бы знать, возможно ли в конце то, что я делаю, или нет, и если да, чтобы получить некоторую помощь, чтобы выяснить, что не так в том, что я делаю. Спасибо!

Ссылки:

...