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).

1  
!7
2  
3  
// stage 1 is the app itself
4  
5  
set flag NoAWT. set flag Android. set flag LeanMode.
6  
set flag NoResourceLoader.
7  
8  
import java.util.*;
9  
import java.util.zip.*;
10  
import java.util.List;
11  
import java.util.regex.*;
12  
import java.util.concurrent.*;
13  
import java.util.concurrent.atomic.*;
14  
import java.io.*;
15  
import java.net.*;
16  
import java.lang.reflect.*;
17  
import java.lang.ref.*;
18  
import java.lang.management.*;
19  
import java.security.*;
20  
import java.security.spec.*;
21  
import java.math.*;
22  
23  
import android.widget.*;
24  
import android.view.*;
25  
import android.view.View;
26  
import android.view.Menu;
27  
import android.view.MenuItem;
28  
import android.widget.Button;
29  
import android.content.Context;
30  
import android.app.Activity;
31  
import android.view.KeyEvent;
32  
import android.view.inputmethod.*;
33  
import android.content.*;
34  
import android.text.*;
35  
36  
sS awarenessID = #1004078;
37  
//sS catProgramID = #1014854;
38  
sS catProgramID = #1023372;
39  
sbool dontStartCat = false;
40  
sbool bootIntoLog = false;
41  
42  
static volatile Class x30;
43  
static volatile bool x30loading, x30loadingFailed;
44  
45  
static List<Prog> programsStarted = new ArrayList<Prog>();
46  
static File defSnip, defargs;
47  
static volatile Class visibleProgram;
48  
sbool dontSwitchToRunningProgram;
49  
static ReliableSingleThread snippetTitleFinder;
50  
51  
static class Prog {
52  
  String snippetID;
53  
  Thread thread;
54  
}
55  
56  
static class Lg {
57  
  static int maxBufferLength = 2048;
58  
  
59  
  Activity context;
60  
  ScrollView sv;
61  
  TextView tv;
62  
  EditText inputView;
63  
  LinearLayout ll;
64  
  StringBuffer buf = new StringBuffer();
65  
  
66  
  Lg(Activity context) {
67  
    this.context = context;
68  
    sv = new ScrollView(context);
69  
    tv = new TextView(context);
70  
    tv.setText(buf.toString());
71  
    sv.addView(tv);
72  
    sv.setLayoutParams(new LinearLayout.LayoutParams(
73  
      LinearLayout.LayoutParams.MATCH_PARENT,
74  
      LinearLayout.LayoutParams.MATCH_PARENT,
75  
      1.0f));
76  
    inputView = new EditText(context);
77  
    inputView.setInputType(InputType.TYPE_CLASS_TEXT); // turn off multiline
78  
    inputView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
79  
      public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
80  
        if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
81  
          String line = inputView.getText().toString();
82  
          try {
83  
            pout3.write((line + "\n").getBytes("UTF-8"));
84  
            pout3.flush();
85  
          } catch (Exception e) {}
86  
          inputView.selectAll();
87  
        }
88  
        return false;
89  
      }
90  
    });
91  
    ll = new LinearLayout(context);
92  
    ll.setOrientation(ll.VERTICAL);
93  
    ll.addView(sv);
94  
    ll.addView(inputView);
95  
  }
96  
  
97  
  View getView() {
98  
    return ll;
99  
  }
100  
  
101  
  void shortenBuffer() {
102  
    while (buf.length() > maxBufferLength) {
103  
      String s = buf.toString();
104  
      int i = s.indexOf('\n');
105  
      if (i < 0) return;
106  
      buf = new StringBuffer(s.substring(i+1));
107  
    }
108  
  }
109  
  
110  
  new UTF8Processor up;
111  
  Lock lock = lock();
112  
  LineBuffer lineBuffer = new(voidfunc(S line) {
113  
    if (startsWithOneOf(line, "[CDS]", "[socket]", "close [socket]")) ret;
114  
    if (eqOneOf(line, "tcp port:5000", "propertyValue:true")) ret;
115  
    print(line + "\n");
116  
  });
117  
  
118  
  void receiveBytes(byte[] b) {
119  
    lock lock;
120  
    lineBuffer.append(funnelBytesThroughUTF8Processor(up, b));
121  
  }
122  
  
123  
  // TODO: coalesce
124  
  void print(final String s) {
125  
    androidUI_noWait(r {
126  
      buf.append(s);
127  
      shortenBuffer();
128  
      tv.setText(buf.toString());
129  
      
130  
      sv.post(new Runnable() {
131  
        public void run() {
132  
          // This method works but animates the scrolling 
133  
          // which looks weird on first load
134  
          sv.fullScroll(View.FOCUS_DOWN);
135  
136  
          // This method works even better because there are no animations.
137  
          //sv.scrollTo(0, sv.getBottom());
138  
        }
139  
      });
140  
    });
141  
  }
142  
  
143  
  void clear() {
144  
    buf.setLength(0);
145  
    print("");
146  
  }
147  
  
148  
  void println(String s) {
149  
    print(s + "\n");
150  
  }
151  
}
152  
153  
public static String snippetToRun;
154  
static TextView statusView;
155  
156  
public static View main(final Context _context) throws Exception {
157  
  final Activity context = _context instanceof Activity ? (Activity) _context : null;
158  
  
159  
  visibleProgram = null;
160  
  
161  
  //System.out.println("676 context: " + _context);
162  
  androidContext = _context;
163  
  
164  
  if (context == null) { // I guess this is for boot time execution
165  
    if (snippetToRun != null) {
166  
      new Thread() {
167  
        public void run() {
168  
          String[] a = { snippetToRun };
169  
          callx30(a);
170  
        }
171  
      }.start();
172  
    }
173  
    return null;
174  
  }
175  
  
176  
  statusView = aTextView();
177  
  preloadx30();
178  
  while (x30 == null && !x30loading && !x30loadingFailed) sleep(10);
179  
180  
  int nInjections = l(injections());
181  
  if (dontSwitchToRunningProgram)
182  
    dontSwitchToRunningProgram = false;
183  
  else if (nInjections > 0) pcall {
184  
    ret getRunningProgramView(nInjections-1);
185  
  }
186  
  
187  
  prepareOptionsMenu();
188  
  
189  
  S dsc = trim(loadTextFile(javaxDataDir("dont-start-cat")));
190  
  if (eq(dsc, "0")) dontStartCat = false;
191  
  else if (eq(dsc, "1")) dontStartCat = true;
192  
  
193  
  if (!dontStartCat &&
194  
    (__javax == null || !isTrue(vm_generalMap_get("dontLoadCat")))) {
195  
    //aHideTitleBar();
196  
    //waitForX30();
197  
    View view = aCatLoadingScreen();
198  
    thread "Cat" {
199  
      waitForX30();
200  
      vm_generalMap_put("dontLoadCat", true);
201  
      for (int i = 0; i < 2; i++) {
202  
        if (i != 0) sleepSeconds(0.5);
203  
      
204  
        // User has already clicked "ADMIN"
205  
        if (print("admin mode: ", androidIsAdminMode())) {
206  
          showStartScreen();
207  
          ret;
208  
        }
209  
      }
210  
      
211  
      if (!bootIntoLog) run_dontShowLog.set(true);
212  
      main.run(context, catProgramID);
213  
    }
214  
    ret view;
215  
  }
216  
217  
  defSnip = new File(userHome(), ".javax/defsnip");
218  
  String id = loadTextFile(defSnip.getPath(), "636");
219  
  defargs = new File(userHome(), ".javax/defargs");
220  
  String arg = loadTextFile(defargs.getPath(), "");
221  
222  
  ScrollView sv = new ScrollView(context);
223  
  LinearLayout ll = new LinearLayout(context);
224  
  ll.setOrientation(LinearLayout.VERTICAL);
225  
  
226  
  ll.addView(statusView);
227  
  
228  
  for i to nInjections: {
229  
    final int _i = i;
230  
    ll.addView(aButton("Back to running program " + (i+1), r { showRunningProgram(_i) }));
231  
  }
232  
  for i to nInjections: {
233  
    final int _i = i;
234  
    ll.addView(aButton("Kill running program " + (i+1), r { killRunningProgram(_i) }));
235  
  }
236  
  
237  
  LinearLayout line1 = new LinearLayout(context);
238  
  line1.addView(aTextView("Snippet ID:"));
239  
  
240  
  final EditText tv = aFontSize(24, new EditText(context));
241  
  // BAD - tv.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
242  
  tv.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_CLASS_NUMBER);
243  
  tv.setText(id);
244  
  line1.addView(tv);
245  
  
246  
  snippetTitleFinder = new ReliableSingleThread(r {
247  
    S id = aGetText(tv);
248  
    if (isSnippetID(id))
249  
      aSetText(statusView, snippetTitle(id));
250  
  });
251  
  
252  
  aOnChange(tv, snippetTitleFinder);
253  
  
254  
  Button btnRun = new Button(context);
255  
  btnRun.setText("Run");
256  
  line1.addView(btnRun);
257  
  
258  
  ll.addView(line1);
259  
  
260  
  final EditText tvArgs = aEditText(arg);
261  
  ll.addView(aHorizontalLinearLayout(
262  
    aTextView("Program arguments:"),
263  
    tvArgs);
264  
265  
  //LinearLayout line3 = new LinearLayout(context);
266  
  
267  
  //deleteDownloadedLibrary(#1101204);
268  
  ll.addView(aImageButton(#1101205,/*aButton("Cat",*/ r {
269  
    main.run(context, catProgramID);
270  
  }));
271  
  
272  
  /*ll.addView(aButton("Start Awareness [" + awarenessID + "]", r {
273  
    saveDef(awarenessID, "");
274  
    main.run(context, awarenessID);
275  
  }));*/
276  
277  
  btnRun.setOnClickListener(new View.OnClickListener() {
278  
    public void onClick(View v) {
279  
      hideKeyboard(context);
280  
      String snippetID = tv.getText().toString();
281  
      String args = tvArgs.getText().toString();
282  
      runSnippet(context, snippetID, args);
283  
    }
284  
  });
285  
286  
  // Show initial status for 1 second, then snippet title
287  
  aLater(1000, snippetTitleFinder);
288  
  
289  
  sv.addView(ll);
290  
  return sv;
291  
}
292  
293  
static void saveDef(String snippetID, String args) {
294  
  try {
295  
    saveTextFile(defSnip.getPath(), snippetID);
296  
    saveTextFile(defargs.getPath(), args);
297  
  } catch (IOException e) {
298  
  }
299  
}
300  
301  
static Lg lg;
302  
303  
static int systemInPipeSize = 4*1024; // 4 K
304  
static PipedInputStream pin3;
305  
static PipedOutputStream pout3;
306  
307  
static new ThreadLocal<Bool> run_dontShowLog;
308  
309  
public static void run(final Activity context, final String mainSnippet, final String... args) {
310  
  bool dontShowLog = isTrue(optParam(run_dontShowLog));
311  
  try {
312  
    pin3 = new PipedInputStream(systemInPipeSize);
313  
    pout3 = new PipedOutputStream(pin3);
314  
  } catch (IOException e) {}
315  
  
316  
  lg = new Lg(context);
317  
  
318  
  OutputStream outputStream = new OutputStream() {
319  
    public void write(int b) {
320  
      lg.receiveBytes(new byte[] {(byte) b});
321  
    }
322  
    
323  
    @Override
324  
    public void write(byte[] b, int off, int len) {
325  
      lg.receiveBytes(subByteArray(b, off, len));
326  
    }
327  
  };
328  
  
329  
  PrintStream ps = new PrintStream(outputStream, true);
330  
  System.setOut(ps);
331  
  System.setErr(ps);
332  
  System.setIn(pin3);
333  
334  
  Prog prog = new Prog();
335  
  prog.snippetID = mainSnippet;
336  
337  
  prog.thread = new Thread() {
338  
    public void run() {
339  
      try {
340  
        String[] a = new String[args.length+1];
341  
        System.arraycopy(args, 0, a, 1, args.length);
342  
        a[0] = mainSnippet;
343  
        callx30(a);
344  
      } catch (Throwable e) {
345  
        System.out.println("Whoa!");
346  
        e.printStackTrace();
347  
      }
348  
    }
349  
  };
350  
  
351  
  programsStarted.add(prog);
352  
  prog.thread.start();
353  
  
354  
  if (!dontShowLog)
355  
    context.setContentView(lg.getView());
356  
}
357  
358  
static void setContentViewInUIThread(final View view) {
359  
  androidUI(r {
360  
    androidActivity().setContentView(view);
361  
  });
362  
}
363  
364  
public static void hideKeyboard(Activity context) {   
365  
  View view = context.getCurrentFocus();
366  
  if (view != null) {
367  
      InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
368  
      inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
369  
  }
370  
}
371  
372  
static void onActivityResult(int requestCode, int resultCode, Intent data) {
373  
  /* TODO?
374  
  if (x30.mainClass != null)
375  
    x30.call(x30.mainClass, "onActivityResult", requestCode, resultCode, data);*/
376  
}
377  
378  
static void onPrepareOptionsPanel(View view, Menu menu) {
379  
  /* TODO
380  
  if (x30.mainClass != null)
381  
    x30.call(x30.mainClass, "onPrepareOptionsPanel", view, menu);*/
382  
}
383  
384  
static boolean onOptionsItemSelected(MenuItem item) {
385  
  /* TODO
386  
  if (x30.mainClass != null)
387  
    return (boolean) x30.call(x30.mainClass, "onOptionsItemSelected", item);*/
388  
  S s = str(item.getTitle());
389  
  print("Item title: " + quote(s));
390  
  if (eqOneOf(s, "Settings", "Tasks"))
391  
    showStartScreen();
392  
  else if (eqic(s, "Show Console"))
393  
    showConsole();
394  
  callOpt(visibleProgram, 'onMenuCommand, s);
395  
  true;
396  
}
397  
398  
svoid waitForX30 {  
399  
  while (x30 == null)
400  
    if (x30loadingFailed) fail("x30 load failed");
401  
    else sleep(10); // guess it's loading
402  
}
403  
404  
static void callx30(S[] args) {
405  
  waitForX30();
406  
  //print("Calling x30 " + join(" ", args));
407  
  pcall {
408  
    set(x30, "androidContext", androidContext);
409  
    ((ThreadLocal) get(x30, 'onProgramLoad)).set(voidfunc(O paa) {
410  
      visibleProgram = (Class) getOpt(paa, 'mainClass);
411  
      //print("Have visible program: " + visibleProgram);
412  
    });
413  
    callMain(x30, args);
414  
    L injections = injections();
415  
    //visibleProgram = (Class) getOpt(last(injections), 'mainClass); // TODO: imprecise if main program tempers with injections
416  
    //print("Have " + l(injections) + " injections, visibleProgram=" + visibleProgram);
417  
    //print("x30 done");
418  
  }
419  
}
420  
421  
svoid preloadx30() { thread { getx30(); } }
422  
423  
static void getx30() {
424  
  try {
425  
    S status = "";
426  
    if (x30 != null) status = "Have x30.";
427  
    else {
428  
      O dataStore = null;
429  
      pcall {
430  
        dataStore = Class.forName("de.tinybrain.javax_allperms.DataStore");
431  
      }
432  
      if (dataStore != null) {
433  
        x30 = __javax = (Class) call(dataStore, "get", "x30");
434  
        if (x30 != null) status = "Have x30 from data store.";
435  
      }
436  
      if (x30 == null) {
437  
        x30loading = true;
438  
        status("Loading x30...");
439  
        Class x30 = loadx30("#1004182");
440  
        callOpt(dataStore, "put", "x30", x30);
441  
        main.x30 = __javax = x30; // use it ourselves
442  
        vmGeneralMap_put("bootstrapper", mc());
443  
        status(status = "x30 loaded.");
444  
      }
445  
      setOpt(x30, "bootUpClass", main.class);
446  
    }
447  
    L injections = injections();
448  
    if (nempty(injections))
449  
      status += " " + n2(injections, "injection");
450  
    status(status);
451  
  } catch e {
452  
    status(getStackTrace(e));
453  
    printStackTrace(e);
454  
    x30loadingFailed = true;
455  
  } finally {
456  
    x30loading = false;
457  
  }
458  
}
459  
460  
static L injections() {
461  
  ret (L) callOpt(x30, 'getInjections);
462  
}
463  
464  
svoid killRunningProgram(int i) {
465  
  try {
466  
    O paa = get(injections(), i);
467  
    if (paa == null) ret;
468  
    call(x30, 'removeInjection, paa);
469  
    showStartScreen();
470  
  } catch e {
471  
    printStackTrace(e);
472  
    status(str(e));
473  
  }
474  
}
475  
476  
svoid showStartScreen() {
477  
  print("showStartScreen");
478  
  androidUI(r {
479  
    dontSwitchToRunningProgram = true;
480  
    androidActivity().setContentView(main(androidContext()));
481  
  });
482  
}
483  
484  
svoid showRunningProgram(int i) {
485  
  View v = getRunningProgramView(i);
486  
  if (v != null)
487  
    setContentViewInUIThread(v);
488  
}
489  
490  
static View getRunningProgramView(int i) {
491  
  O paa = get(injections(), i);
492  
  if (paa == null) ret null with status("No running program to show");
493  
  Class mainClass = cast getOpt(paa, 'mainClass);
494  
  View view = cast getOpt(mainClass, 'androidShow_view);
495  
  if (view == null)
496  
    //ret null with status("Program has no view to show");
497  
    view = lg.getView(); // show log instead
498  
  print("Switched to program " + get(paa, 'progID));
499  
  visibleProgram = mainClass;
500  
  ViewGroup group = (ViewGroup) view.getParent();
501  
  if (group != null)
502  
    group.removeView(view);
503  
  ret view;
504  
}
505  
506  
svoid status(S s) {
507  
  aSetText(statusView, s);
508  
  print(s);
509  
}
510  
511  
static Class<?> loadx30(String programID) ctex {
512  
  System.out.println("Program ID: " + programID);
513  
  S url = tb_mainServer() + "/dexcompile.php?id=" + parseSnippetID(programID);
514  
  status("Loading DEX: " + url);
515  
  byte[] dexData = loadBinaryPage(url);
516  
  status("Loaded something");
517  
  if (!isDex(dexData))
518  
    throw new RuntimeException("Dex generation error");
519  
  status("DEX loaded");
520  
  System.out.println("Dex loaded: " + dexData.length + "b");
521  
522  
  File dexDir = makeAndroidTempDir();
523  
  File dexFile = new File(dexDir, System.currentTimeMillis() + ".dex");
524  
  File dexOutputDir = makeAndroidTempDir();
525  
526  
  System.out.println("Saving dex to: " + dexDir.getAbsolutePath());
527  
  try {
528  
    saveBinaryFile(dexFile.getPath(), dexData);
529  
  } catch (Throwable e) {
530  
    System.out.println("Whoa!");
531  
    throw new RuntimeException(e);
532  
  }
533  
534  
  System.out.println("Getting parent class loader.");
535  
  ClassLoader parentClassLoader =
536  
    main.class.getClassLoader().getParent();
537  
538  
  //System.out.println("Making DexClassLoader.");
539  
  //DexClassLoader classLoader = new DexClassLoader(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null,
540  
  //  parentClassLoader);
541  
  Class dcl = Class.forName("dalvik.system.DexClassLoader");
542  
  Object classLoader = dcl.getConstructors()[0].newInstance(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null,
543  
    parentClassLoader);
544  
545  
  System.out.println("Loading main class.");
546  
  Class<?> theClass = (Class<?>) call(classLoader, "loadClass", "x30");
547  
548  
  System.out.println("Main class loaded.");
549  
  try {
550  
    set(theClass, "androidContext", androidContext);
551  
  } catch (Throwable e) {}
552  
553  
  setVars(theClass, programID);
554  
  hotwire_copyOver(theClass);
555  
  return theClass;
556  
}
557  
558  
static void setVars(Class<?> theClass, String programID) {
559  
  try {
560  
    set(theClass, "programID", programID);
561  
  } catch (Throwable e) {}
562  
563  
  try {
564  
    set(theClass, "__javax", x30);
565  
  } catch (Throwable e) {}
566  
}
567  
568  
static String getConsoleOutput() {
569  
  ret lg.buf.toString();
570  
}
571  
572  
svoid prepareOptionsMenu {
573  
  pcall {
574  
    Menu menu = cast getOpt(androidActivity(), 'optionsMenu);
575  
    if (menu == null) ret;
576  
    if (menu.size() < 2) {
577  
      aRemoveItemFromMenu(menu, "Settings");
578  
      menu.add("Tasks");
579  
      menu.add("Show Console");
580  
    }
581  
  }
582  
}
583  
584  
// fix for when there is no x30 yet
585  
static void mapMethodLike vmBus_send(String msg, Object... args) {
586  
  pcall-silent {
587  
    Object arg = vmBus_wrapArgs(args);
588  
    pcallFAll(vm_busListeners_live(), msg, arg);
589  
    pcallFAll(vm_busListenersByMessage_live().get(msg), msg, arg);
590  
  }
591  
}
592  
593  
svoid showConsole {
594  
  visibleProgram = null;
595  
  androidUI {
596  
    androidActivity().setContentView(lg.getView());
597  
  }
598  
}
599  
600  
svoid runSnippet(final Activity context, fS snippetID, fS args) {
601  
  androidUI {
602  
    androidUnsetAdminMode();
603  
    S text = "Running: " + snippetID;
604  
    Toast.makeText(context, text, 2000).show();
605  
    
606  
    saveDef(snippetID, args);
607  
    
608  
    // TODO: quoted args
609  
    main.run(context, snippetID, unnull(args).split(" +"));
610  
  }
611  
}

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: 2137 / 2118
Version history: 144 change(s)
Referenced in: [show references]