Alexandre Julliard : wineandroid: Install libraries from the package assets if present.

Alexandre Julliard julliard at winehq.org
Tue May 30 16:05:13 CDT 2017


Module: wine
Branch: master
Commit: da2522becb3c167ddba5457ee460a7194eb505e9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=da2522becb3c167ddba5457ee460a7194eb505e9

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue May 30 14:19:57 2017 +0200

wineandroid: Install libraries from the package assets if present.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/wineandroid.drv/Makefile.in       |   5 +
 dlls/wineandroid.drv/WineActivity.java | 164 +++++++++++++++++++++++++++++++++
 2 files changed, 169 insertions(+)

diff --git a/dlls/wineandroid.drv/Makefile.in b/dlls/wineandroid.drv/Makefile.in
index 42c6926..0001dec 100644
--- a/dlls/wineandroid.drv/Makefile.in
+++ b/dlls/wineandroid.drv/Makefile.in
@@ -8,4 +8,9 @@ EXTRA_TARGETS = wine-debug.apk
 all: wine-debug.apk
 
 wine-debug.apk: build.gradle $(srcdir)/AndroidManifest.xml $(srcdir)/WineActivity.java $(srcdir)/wine.svg
+	(test -d assets && \
+	  rm -f assets/files.sum assets/sums.sum && \
+	  sha256sum `find assets -type f -print` | sed 's/ assets\// /' >files.sum && \
+	  sha256sum files.sum >sums.sum && \
+	  mv files.sum sums.sum assets) || rm -rf assets
 	gradle -q assembleDebug && mv build/outputs/apk/wine-debug.apk .
diff --git a/dlls/wineandroid.drv/WineActivity.java b/dlls/wineandroid.drv/WineActivity.java
index ceac1b6..84ce463 100644
--- a/dlls/wineandroid.drv/WineActivity.java
+++ b/dlls/wineandroid.drv/WineActivity.java
@@ -21,13 +21,177 @@
 package org.winehq.wine;
 
 import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.SharedPreferences;
+import android.os.Build;
 import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 
 public class WineActivity extends Activity
 {
+    private final String LOGTAG = "wine";
+    private ProgressDialog progress_dialog;
+
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate( savedInstanceState );
+
+        requestWindowFeature( android.view.Window.FEATURE_NO_TITLE );
+
+        new Thread( new Runnable() { public void run() { loadWine(); }} ).start();
+    }
+
+    private void loadWine()
+    {
+        copyAssetFiles();
+        runOnUiThread( new Runnable() { public void run() { progress_dialog.dismiss(); }});
+    }
+
+    private void createProgressDialog( final int max, final String message )
+    {
+        runOnUiThread( new Runnable() { public void run() {
+            if (progress_dialog != null) progress_dialog.dismiss();
+            progress_dialog = new ProgressDialog( WineActivity.this );
+            progress_dialog.setProgressStyle( max > 0 ? ProgressDialog.STYLE_HORIZONTAL
+                                              : ProgressDialog.STYLE_SPINNER );
+            progress_dialog.setTitle( "Wine" );
+            progress_dialog.setMessage( message );
+            progress_dialog.setCancelable( false );
+            progress_dialog.setMax( max );
+            progress_dialog.show();
+        }});
+
+    }
+
+    private final boolean isFileWanted( String name )
+    {
+        if (name.equals( "files.sum" )) return true;
+        if (name.startsWith( "share/" )) return true;
+        if (name.startsWith( Build.CPU_ABI + "/system/" )) return false;
+        if (name.startsWith( Build.CPU_ABI + "/" )) return true;
+        if (name.startsWith( "x86/" )) return true;
+        return false;
+    }
+
+    private final boolean isFileExecutable( String name )
+    {
+        return name.startsWith( Build.CPU_ABI + "/" ) || name.startsWith( "x86/" );
+    }
+
+    private final HashMap<String,String> readMapFromInputStream( InputStream in )
+    {
+        HashMap<String,String> map = new HashMap<String,String>();
+        String str;
+
+        try
+        {
+            BufferedReader reader = new BufferedReader( new InputStreamReader( in, "UTF-8" ));
+            while ((str = reader.readLine()) != null)
+            {
+                String entry[] = str.split( "\\s+", 2 );
+                if (entry.length == 2 && isFileWanted( entry[1] )) map.put( entry[1], entry[0] );
+            }
+        }
+        catch( IOException e ) { }
+        return map;
+    }
+
+    private final HashMap<String,String> readMapFromDiskFile( String file )
+    {
+        try
+        {
+            return readMapFromInputStream( new FileInputStream( new File( getFilesDir(), file )));
+        }
+        catch( IOException e ) { return new HashMap<String,String>(); }
+    }
+
+    private final HashMap<String,String> readMapFromAssetFile( String file )
+    {
+        try
+        {
+            return readMapFromInputStream( getAssets().open( file ) );
+        }
+        catch( IOException e ) { return new HashMap<String,String>(); }
+    }
+
+    private final void copyAssetFile( String src )
+    {
+        File dest = new File( getFilesDir(), src );
+        try
+        {
+            Log.i( LOGTAG, "extracting " + dest );
+            dest.getParentFile().mkdirs();
+            dest.delete();
+            if (dest.createNewFile())
+            {
+                InputStream in = getAssets().open( src );
+                FileOutputStream out = new FileOutputStream( dest );
+                int read;
+                byte[] buffer = new byte[65536];
+
+                while ((read = in.read( buffer )) > 0) out.write( buffer, 0, read );
+                out.close();
+                if (isFileExecutable( src )) dest.setExecutable( true, true );
+            }
+            else
+                Log.i( LOGTAG, "Failed to create file "  + dest );
+        }
+        catch( IOException e )
+        {
+            Log.i( LOGTAG, "Failed to copy asset file to " + dest );
+            dest.delete();
+        }
+    }
+
+    private final void deleteAssetFile( String src )
+    {
+        File dest = new File( getFilesDir(), src );
+        Log.i( LOGTAG, "deleting " + dest );
+        dest.delete();
+    }
+
+    private final void copyAssetFiles()
+    {
+        String new_sum = readMapFromAssetFile( "sums.sum" ).get( "files.sum" );
+        if (new_sum == null) return;  // no assets
+
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( this );
+        String old_sum = prefs.getString( "files.sum", "" );
+        if (old_sum.equals( new_sum )) return;  // no change
+        prefs.edit().putString( "files.sum", new_sum ).apply();
+
+        HashMap<String,String> existing_files = readMapFromDiskFile( "files.sum" );
+        HashMap<String,String> new_files = readMapFromAssetFile( "files.sum" );
+        ArrayList<String> copy_files = new ArrayList<String>();
+        copy_files.add( "files.sum" );
+
+        for (Map.Entry<String, String> entry : new_files.entrySet())
+        {
+            String name = entry.getKey();
+            if (!entry.getValue().equals( existing_files.remove( name ))) copy_files.add( name );
+        }
+
+        createProgressDialog( copy_files.size(), "Extracting files..." );
+
+        for (String name : existing_files.keySet()) deleteAssetFile( name );
+
+        for (String name : copy_files)
+        {
+            copyAssetFile( name );
+            runOnUiThread( new Runnable() { public void run() {
+                progress_dialog.incrementProgressBy( 1 ); }});
+        }
     }
 }




More information about the wine-cvs mailing list