Forum Xamarin.Android

Targeting Android Q - avoiding W^X violation

tepnilkatepnilka USMember ✭✭

Hi everyone!

After Google announced new restrictions for Android Q making folder writable XOR executable, I am a bit confused where to put executable files from my example and how to properly use them. Maybe I am almost there but maybe I am miles away on completely wrong path... :D

This is fully working example when I run in Debug mode. I initialize Process feeding it with 3rd party executable 'stockfish.so'.

    ProcessStartInfo psi = new ProcessStartInfo();

    string engineUsed = "stockfish.so";                

    psi.FileName = Path.Combine(context.ApplicationInfo.NativeLibraryDir, engineUsed);
    psi.UseShellExecute = false;
    psi.CreateNoWindow = true;

    psi.RedirectStandardInput = true;
    psi.RedirectStandardOutput = true;
    psi.RedirectStandardError = true;

    stockfishProcess = new System.Diagnostics.Process();

    stockfishProcess.OutputDataReceived += OnDataReceived;
    stockfishProcess.StartInfo = psi;
    stockfishProcess.Start();

    stockfishProcess.PriorityClass = ProcessPriorityClass.Idle;

    stockfishProcess.BeginErrorReadLine();
    stockfishProcess.BeginOutputReadLine();
    initialized = true;

These executables communicate purely using input and output text messages as described bellow. There are no calls to functions of this 3rd party executable. This is standard used in chess engines for last 20 years and I have no control over those *.so files. I must take them as they are with all their communicating logic.

    public void SendLine(string command)
    {
        stockfishProcess.StandardInput.WriteLine(command);
        stockfishProcess.StandardInput.Flush();
    }
    private void OnDataReceived(object sender, DataReceivedEventArgs e)
    {
        if (e.Data == null)
            return;

        lb.OnStockfishDataUpdate(e.Data);
    }

My question is very simple: What is the way to keep my app functionality once I start targeting Android Q? Before the restriction I used two Raw resources for v7a and v8a ABIs, loading better one to app directory and then execute it as above.

As I mentioned, this example works for me in Debug mode and I presume it would be fine on Android Q too as the jniLibs is read-only. In Release mode the 'stockfish.so' file however doesn't exist.

  1. Is this the correct design to make described functionality work on my part?
  2. What am I missing with the Debug/Release modes?
  3. I strongly prefer 1 apk file. I don't want additional complexity for 50 kilobytes if not absolutely neccessary.

I was playing with android.bundle.enableUncompressedNativeLibs
and android:extractNativeLibs in application tag of AndroidManifest,
but it didn't lead me anywhere.

I read ton of text regarding app bundles regarding similar issues, but isn't it possible to make this task easier?

Best Answer

  • tepnilkatepnilka USMember ✭✭
    Accepted Answer
    I must do a bit testing but the problem seems to be that the file "stockfish.so" had to be renamed to something starting with "lib", eg. "libsf.so". Then together with manifest application entry "android:extractNativeLibs=true" the file started to be extracted into "context.ApplicationInfo.NativeLibraryDir" successfully and I can use it B)

Answers

  • tepnilkatepnilka USMember ✭✭
    Accepted Answer
    I must do a bit testing but the problem seems to be that the file "stockfish.so" had to be renamed to something starting with "lib", eg. "libsf.so". Then together with manifest application entry "android:extractNativeLibs=true" the file started to be extracted into "context.ApplicationInfo.NativeLibraryDir" successfully and I can use it B)
Sign In or Register to comment.