Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

611
LINES

< > BotCompany Repo | #676 // Boot-up code for JavaX/Android (stage 2, JavaX, LIVE)

JavaX source code (Android) [tags: use-pretranspiled] - run with: the app

Libraryless. Click here for Pure Java version (5869L/41K/145K).

!7

// stage 1 is the app itself

set flag NoAWT. set flag Android. set flag LeanMode.
set flag NoResourceLoader.

import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.math.*;

import android.widget.*;
import android.view.*;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.content.Context;
import android.app.Activity;
import android.view.KeyEvent;
import android.view.inputmethod.*;
import android.content.*;
import android.text.*;

sS awarenessID = #1004078;
//sS catProgramID = #1014854;
sS catProgramID = #1023372;
sbool dontStartCat = false;
sbool bootIntoLog = false;

static volatile Class x30;
static volatile bool x30loading, x30loadingFailed;

static List<Prog> programsStarted = new ArrayList<Prog>();
static File defSnip, defargs;
static volatile Class visibleProgram;
sbool dontSwitchToRunningProgram;
static ReliableSingleThread snippetTitleFinder;

static class Prog {
  String snippetID;
  Thread thread;
}

static class Lg {
  static int maxBufferLength = 2048;
  
  Activity context;
  ScrollView sv;
  TextView tv;
  EditText inputView;
  LinearLayout ll;
  StringBuffer buf = new StringBuffer();
  
  Lg(Activity context) {
    this.context = context;
    sv = new ScrollView(context);
    tv = new TextView(context);
    tv.setText(buf.toString());
    sv.addView(tv);
    sv.setLayoutParams(new LinearLayout.LayoutParams(
      LinearLayout.LayoutParams.MATCH_PARENT,
      LinearLayout.LayoutParams.MATCH_PARENT,
      1.0f));
    inputView = new EditText(context);
    inputView.setInputType(InputType.TYPE_CLASS_TEXT); // turn off multiline
    inputView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
      public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
          String line = inputView.getText().toString();
          try {
            pout3.write((line + "\n").getBytes("UTF-8"));
            pout3.flush();
          } catch (Exception e) {}
          inputView.selectAll();
        }
        return false;
      }
    });
    ll = new LinearLayout(context);
    ll.setOrientation(ll.VERTICAL);
    ll.addView(sv);
    ll.addView(inputView);
  }
  
  View getView() {
    return ll;
  }
  
  void shortenBuffer() {
    while (buf.length() > maxBufferLength) {
      String s = buf.toString();
      int i = s.indexOf('\n');
      if (i < 0) return;
      buf = new StringBuffer(s.substring(i+1));
    }
  }
  
  new UTF8Processor up;
  Lock lock = lock();
  LineBuffer lineBuffer = new(voidfunc(S line) {
    if (startsWithOneOf(line, "[CDS]", "[socket]", "close [socket]")) ret;
    if (eqOneOf(line, "tcp port:5000", "propertyValue:true")) ret;
    print(line + "\n");
  });
  
  void receiveBytes(byte[] b) {
    lock lock;
    lineBuffer.append(funnelBytesThroughUTF8Processor(up, b));
  }
  
  // TODO: coalesce
  void print(final String s) {
    androidUI_noWait(r {
      buf.append(s);
      shortenBuffer();
      tv.setText(buf.toString());
      
      sv.post(new Runnable() {
        public void run() {
          // This method works but animates the scrolling 
          // which looks weird on first load
          sv.fullScroll(View.FOCUS_DOWN);

          // This method works even better because there are no animations.
          //sv.scrollTo(0, sv.getBottom());
        }
      });
    });
  }
  
  void clear() {
    buf.setLength(0);
    print("");
  }
  
  void println(String s) {
    print(s + "\n");
  }
}

public static String snippetToRun;
static TextView statusView;

public static View main(final Context _context) throws Exception {
  final Activity context = _context instanceof Activity ? (Activity) _context : null;
  
  visibleProgram = null;
  
  //System.out.println("676 context: " + _context);
  androidContext = _context;
  
  if (context == null) { // I guess this is for boot time execution
    if (snippetToRun != null) {
      new Thread() {
        public void run() {
          String[] a = { snippetToRun };
          callx30(a);
        }
      }.start();
    }
    return null;
  }
  
  statusView = aTextView();
  preloadx30();
  while (x30 == null && !x30loading && !x30loadingFailed) sleep(10);

  int nInjections = l(injections());
  if (dontSwitchToRunningProgram)
    dontSwitchToRunningProgram = false;
  else if (nInjections > 0) pcall {
    ret getRunningProgramView(nInjections-1);
  }
  
  prepareOptionsMenu();
  
  S dsc = trim(loadTextFile(javaxDataDir("dont-start-cat")));
  if (eq(dsc, "0")) dontStartCat = false;
  else if (eq(dsc, "1")) dontStartCat = true;
  
  if (!dontStartCat &&
    (__javax == null || !isTrue(vm_generalMap_get("dontLoadCat")))) {
    //aHideTitleBar();
    //waitForX30();
    View view = aCatLoadingScreen();
    thread "Cat" {
      waitForX30();
      vm_generalMap_put("dontLoadCat", true);
      for (int i = 0; i < 2; i++) {
        if (i != 0) sleepSeconds(0.5);
      
        // User has already clicked "ADMIN"
        if (print("admin mode: ", androidIsAdminMode())) {
          showStartScreen();
          ret;
        }
      }
      
      if (!bootIntoLog) run_dontShowLog.set(true);
      main.run(context, catProgramID);
    }
    ret view;
  }

  defSnip = new File(userHome(), ".javax/defsnip");
  String id = loadTextFile(defSnip.getPath(), "636");
  defargs = new File(userHome(), ".javax/defargs");
  String arg = loadTextFile(defargs.getPath(), "");

  ScrollView sv = new ScrollView(context);
  LinearLayout ll = new LinearLayout(context);
  ll.setOrientation(LinearLayout.VERTICAL);
  
  ll.addView(statusView);
  
  for i to nInjections: {
    final int _i = i;
    ll.addView(aButton("Back to running program " + (i+1), r { showRunningProgram(_i) }));
  }
  for i to nInjections: {
    final int _i = i;
    ll.addView(aButton("Kill running program " + (i+1), r { killRunningProgram(_i) }));
  }
  
  LinearLayout line1 = new LinearLayout(context);
  line1.addView(aTextView("Snippet ID:"));
  
  final EditText tv = aFontSize(24, new EditText(context));
  // BAD - tv.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
  tv.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_CLASS_NUMBER);
  tv.setText(id);
  line1.addView(tv);
  
  snippetTitleFinder = new ReliableSingleThread(r {
    S id = aGetText(tv);
    if (isSnippetID(id))
      aSetText(statusView, snippetTitle(id));
  });
  
  aOnChange(tv, snippetTitleFinder);
  
  Button btnRun = new Button(context);
  btnRun.setText("Run");
  line1.addView(btnRun);
  
  ll.addView(line1);
  
  final EditText tvArgs = aEditText(arg);
  ll.addView(aHorizontalLinearLayout(
    aTextView("Program arguments:"),
    tvArgs);

  //LinearLayout line3 = new LinearLayout(context);
  
  //deleteDownloadedLibrary(#1101204);
  ll.addView(aImageButton(#1101205,/*aButton("Cat",*/ r {
    main.run(context, catProgramID);
  }));
  
  /*ll.addView(aButton("Start Awareness [" + awarenessID + "]", r {
    saveDef(awarenessID, "");
    main.run(context, awarenessID);
  }));*/

  btnRun.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
      hideKeyboard(context);
      String snippetID = tv.getText().toString();
      String args = tvArgs.getText().toString();
      runSnippet(context, snippetID, args);
    }
  });

  // Show initial status for 1 second, then snippet title
  aLater(1000, snippetTitleFinder);
  
  sv.addView(ll);
  return sv;
}

static void saveDef(String snippetID, String args) {
  try {
    saveTextFile(defSnip.getPath(), snippetID);
    saveTextFile(defargs.getPath(), args);
  } catch (IOException e) {
  }
}

static Lg lg;

static int systemInPipeSize = 4*1024; // 4 K
static PipedInputStream pin3;
static PipedOutputStream pout3;

static new ThreadLocal<Bool> run_dontShowLog;

public static void run(final Activity context, final String mainSnippet, final String... args) {
  bool dontShowLog = isTrue(optParam(run_dontShowLog));
  try {
    pin3 = new PipedInputStream(systemInPipeSize);
    pout3 = new PipedOutputStream(pin3);
  } catch (IOException e) {}
  
  lg = new Lg(context);
  
  OutputStream outputStream = new OutputStream() {
    public void write(int b) {
      lg.receiveBytes(new byte[] {(byte) b});
    }
    
    @Override
    public void write(byte[] b, int off, int len) {
      lg.receiveBytes(subByteArray(b, off, len));
    }
  };
  
  PrintStream ps = new PrintStream(outputStream, true);
  System.setOut(ps);
  System.setErr(ps);
  System.setIn(pin3);

  Prog prog = new Prog();
  prog.snippetID = mainSnippet;

  prog.thread = new Thread() {
    public void run() {
      try {
        String[] a = new String[args.length+1];
        System.arraycopy(args, 0, a, 1, args.length);
        a[0] = mainSnippet;
        callx30(a);
      } catch (Throwable e) {
        System.out.println("Whoa!");
        e.printStackTrace();
      }
    }
  };
  
  programsStarted.add(prog);
  prog.thread.start();
  
  if (!dontShowLog)
    context.setContentView(lg.getView());
}

static void setContentViewInUIThread(final View view) {
  androidUI(r {
    androidActivity().setContentView(view);
  });
}

public static void hideKeyboard(Activity context) {   
  View view = context.getCurrentFocus();
  if (view != null) {
      InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
      inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
  }
}

static void onActivityResult(int requestCode, int resultCode, Intent data) {
  /* TODO?
  if (x30.mainClass != null)
    x30.call(x30.mainClass, "onActivityResult", requestCode, resultCode, data);*/
}

static void onPrepareOptionsPanel(View view, Menu menu) {
  /* TODO
  if (x30.mainClass != null)
    x30.call(x30.mainClass, "onPrepareOptionsPanel", view, menu);*/
}

static boolean onOptionsItemSelected(MenuItem item) {
  /* TODO
  if (x30.mainClass != null)
    return (boolean) x30.call(x30.mainClass, "onOptionsItemSelected", item);*/
  S s = str(item.getTitle());
  print("Item title: " + quote(s));
  if (eqOneOf(s, "Settings", "Tasks"))
    showStartScreen();
  else if (eqic(s, "Show Console"))
    showConsole();
  callOpt(visibleProgram, 'onMenuCommand, s);
  true;
}

svoid waitForX30 {  
  while (x30 == null)
    if (x30loadingFailed) fail("x30 load failed");
    else sleep(10); // guess it's loading
}

static void callx30(S[] args) {
  waitForX30();
  //print("Calling x30 " + join(" ", args));
  pcall {
    set(x30, "androidContext", androidContext);
    ((ThreadLocal) get(x30, 'onProgramLoad)).set(voidfunc(O paa) {
      visibleProgram = (Class) getOpt(paa, 'mainClass);
      //print("Have visible program: " + visibleProgram);
    });
    callMain(x30, args);
    L injections = injections();
    //visibleProgram = (Class) getOpt(last(injections), 'mainClass); // TODO: imprecise if main program tempers with injections
    //print("Have " + l(injections) + " injections, visibleProgram=" + visibleProgram);
    //print("x30 done");
  }
}

svoid preloadx30() { thread { getx30(); } }

static void getx30() {
  try {
    S status = "";
    if (x30 != null) status = "Have x30.";
    else {
      O dataStore = null;
      pcall {
        dataStore = Class.forName("de.tinybrain.javax_allperms.DataStore");
      }
      if (dataStore != null) {
        x30 = __javax = (Class) call(dataStore, "get", "x30");
        if (x30 != null) status = "Have x30 from data store.";
      }
      if (x30 == null) {
        x30loading = true;
        status("Loading x30...");
        Class x30 = loadx30("#1004182");
        callOpt(dataStore, "put", "x30", x30);
        main.x30 = __javax = x30; // use it ourselves
        vmGeneralMap_put("bootstrapper", mc());
        status(status = "x30 loaded.");
      }
      setOpt(x30, "bootUpClass", main.class);
    }
    L injections = injections();
    if (nempty(injections))
      status += " " + n2(injections, "injection");
    status(status);
  } catch e {
    status(getStackTrace(e));
    printStackTrace(e);
    x30loadingFailed = true;
  } finally {
    x30loading = false;
  }
}

static L injections() {
  ret (L) callOpt(x30, 'getInjections);
}

svoid killRunningProgram(int i) {
  try {
    O paa = get(injections(), i);
    if (paa == null) ret;
    call(x30, 'removeInjection, paa);
    showStartScreen();
  } catch e {
    printStackTrace(e);
    status(str(e));
  }
}

svoid showStartScreen() {
  print("showStartScreen");
  androidUI(r {
    dontSwitchToRunningProgram = true;
    androidActivity().setContentView(main(androidContext()));
  });
}

svoid showRunningProgram(int i) {
  View v = getRunningProgramView(i);
  if (v != null)
    setContentViewInUIThread(v);
}

static View getRunningProgramView(int i) {
  O paa = get(injections(), i);
  if (paa == null) ret null with status("No running program to show");
  Class mainClass = cast getOpt(paa, 'mainClass);
  View view = cast getOpt(mainClass, 'androidShow_view);
  if (view == null)
    //ret null with status("Program has no view to show");
    view = lg.getView(); // show log instead
  print("Switched to program " + get(paa, 'progID));
  visibleProgram = mainClass;
  ViewGroup group = (ViewGroup) view.getParent();
  if (group != null)
    group.removeView(view);
  ret view;
}

svoid status(S s) {
  aSetText(statusView, s);
  print(s);
}

static Class<?> loadx30(String programID) ctex {
  System.out.println("Program ID: " + programID);
  S url = tb_mainServer() + "/dexcompile.php?id=" + parseSnippetID(programID);
  status("Loading DEX: " + url);
  byte[] dexData = loadBinaryPage(url);
  status("Loaded something");
  if (!isDex(dexData))
    throw new RuntimeException("Dex generation error");
  status("DEX loaded");
  System.out.println("Dex loaded: " + dexData.length + "b");

  File dexDir = makeAndroidTempDir();
  File dexFile = new File(dexDir, System.currentTimeMillis() + ".dex");
  File dexOutputDir = makeAndroidTempDir();

  System.out.println("Saving dex to: " + dexDir.getAbsolutePath());
  try {
    saveBinaryFile(dexFile.getPath(), dexData);
  } catch (Throwable e) {
    System.out.println("Whoa!");
    throw new RuntimeException(e);
  }

  System.out.println("Getting parent class loader.");
  ClassLoader parentClassLoader =
    main.class.getClassLoader().getParent();

  //System.out.println("Making DexClassLoader.");
  //DexClassLoader classLoader = new DexClassLoader(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null,
  //  parentClassLoader);
  Class dcl = Class.forName("dalvik.system.DexClassLoader");
  Object classLoader = dcl.getConstructors()[0].newInstance(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null,
    parentClassLoader);

  System.out.println("Loading main class.");
  Class<?> theClass = (Class<?>) call(classLoader, "loadClass", "x30");

  System.out.println("Main class loaded.");
  try {
    set(theClass, "androidContext", androidContext);
  } catch (Throwable e) {}

  setVars(theClass, programID);
  hotwire_copyOver(theClass);
  return theClass;
}

static void setVars(Class<?> theClass, String programID) {
  try {
    set(theClass, "programID", programID);
  } catch (Throwable e) {}

  try {
    set(theClass, "__javax", x30);
  } catch (Throwable e) {}
}

static String getConsoleOutput() {
  ret lg.buf.toString();
}

svoid prepareOptionsMenu {
  pcall {
    Menu menu = cast getOpt(androidActivity(), 'optionsMenu);
    if (menu == null) ret;
    if (menu.size() < 2) {
      aRemoveItemFromMenu(menu, "Settings");
      menu.add("Tasks");
      menu.add("Show Console");
    }
  }
}

// fix for when there is no x30 yet
static void mapMethodLike vmBus_send(String msg, Object... args) {
  pcall-silent {
    Object arg = vmBus_wrapArgs(args);
    pcallFAll(vm_busListeners_live(), msg, arg);
    pcallFAll(vm_busListenersByMessage_live().get(msg), msg, arg);
  }
}

svoid showConsole {
  visibleProgram = null;
  androidUI {
    androidActivity().setContentView(lg.getView());
  }
}

svoid runSnippet(final Activity context, fS snippetID, fS args) {
  androidUI {
    androidUnsetAdminMode();
    S text = "Running: " + snippetID;
    Toast.makeText(context, text, 2000).show();
    
    saveDef(snippetID, args);
    
    // TODO: quoted args
    main.run(context, snippetID, unnull(args).split(" +"));
  }
}

Author comment

hide keyboard
scroll down console
print userHome
shortenBuffer (stdout)

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv

Comments [hide]

ID Author/Program Comment Date
673 #1000610 (pitcher) 2015-08-18 00:07:07
672 #1000604 (pitcher) 2015-08-20 15:28:24

add comment

Snippet ID: #676
Snippet name: Boot-up code for JavaX/Android (stage 2, JavaX, LIVE)
Eternal ID of this version: #676/145
Text MD5: 6cd731fcd5bb1e3dfbfc34798023b6b4
Transpilation MD5: 257c25ba7a08afcfb679b285a24bf932
Author: stefan
Category: javax
Type: JavaX source code (Android)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2020-02-16 16:05:45
Source code size: 17333 bytes / 611 lines
Pitched / IR pitched: No / No
Views / Downloads: 2037 / 1999
Version history: 144 change(s)
Referenced in: [show references]