Compare commits

..

No commits in common. "master" and "4.3.0" have entirely different histories.

140 changed files with 1922 additions and 6251 deletions

5
.firebaserc Normal file
View file

@ -0,0 +1,5 @@
{
"projects": {
"default": "vectras-1678b"
}
}

View file

@ -32,7 +32,6 @@ body:
options:
- Latest
- Beta
- 4.3.0
- 4.2.0
- 4.1.0
- 4.0.0

View file

@ -161,13 +161,7 @@ Help support the project by contributing!
## ⭐ Star History
<a href="https://www.star-history.com/?type=date&legend=top-left&repos=xoureldeen%2FVectras-VM-Android%2CAnBui2004%2FVectras-VM-Emu-Android">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=xoureldeen/Vectras-VM-Android%2CAnBui2004/Vectras-VM-Emu-Android&type=date&theme=dark&legend=top-left&sealed_token=tCBSpkm0wCO-niH9BZfotAc5o9pw1qYcHmnl_Tf0CGpqLiLKWlKV8B83nEWskG5QlSQU-aSX65HooXNo165vG8U7TUp9EOPXZiKJpeAroPcxaIGR2G0eTQ" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=xoureldeen/Vectras-VM-Android%2CAnBui2004/Vectras-VM-Emu-Android&type=date&legend=top-left&sealed_token=tCBSpkm0wCO-niH9BZfotAc5o9pw1qYcHmnl_Tf0CGpqLiLKWlKV8B83nEWskG5QlSQU-aSX65HooXNo165vG8U7TUp9EOPXZiKJpeAroPcxaIGR2G0eTQ" />
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=xoureldeen/Vectras-VM-Android%2CAnBui2004/Vectras-VM-Emu-Android&type=date&legend=top-left&sealed_token=tCBSpkm0wCO-niH9BZfotAc5o9pw1qYcHmnl_Tf0CGpqLiLKWlKV8B83nEWskG5QlSQU-aSX65HooXNo165vG8U7TUp9EOPXZiKJpeAroPcxaIGR2G0eTQ" />
</picture>
</a>
[![Star History Chart](https://api.star-history.com/svg?repos=xoureldeen/Vectras-VM-Android,AnBui2004/Vectras-VM-Emu-Android&type=date&legend=top-left)](https://www.star-history.com/#xoureldeen/Vectras-VM-Android&AnBui2004/Vectras-VM-Emu-Android&type=date&legend=top-left)
[ico-telegram]: https://img.shields.io/badge/Telegram-2CA5E0?logo=telegram&logoColor=white
[ico-discord]: https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white

View file

@ -2,7 +2,6 @@ plugins {
id 'com.android.application'
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
id 'com.google.android.gms.oss-licenses-plugin'
}
android {
@ -13,8 +12,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
versionCode 140
versionName "4.3.6"
versionCode 134
versionName "4.3.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
@ -124,6 +123,4 @@ dependencies {
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
implementation libs.play.services.oss.licenses
}

View file

@ -47,16 +47,6 @@
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".settings.EqualizerActivity"
android:configChanges="orientation|screenSize|keyboardHidden|smallestScreenSize|screenLayout"
android:exported="false"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".settings.FilePickerSettingsActivity"
android:configChanges="orientation|screenSize|keyboardHidden|smallestScreenSize|screenLayout"
android:exported="false"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".settings.SearchSettingsActivity"
android:configChanges="orientation|screenSize|keyboardHidden|smallestScreenSize|screenLayout"

View file

@ -859,10 +859,10 @@ public class VncCanvas extends AppCompatImageView {
}
// Useful shortcuts for modifier masks.
public final static int CTRL_MASK = KeyEvent.META_SYM_ON;
public final static int SHIFT_MASK = KeyEvent.META_SHIFT_ON;
public final static int META_MASK = 0;
public final static int ALT_MASK = KeyEvent.META_ALT_ON;
final static int CTRL_MASK = KeyEvent.META_SYM_ON;
final static int SHIFT_MASK = KeyEvent.META_SHIFT_ON;
final static int META_MASK = 0;
final static int ALT_MASK = KeyEvent.META_ALT_ON;
private static final int MOUSE_BUTTON_NONE = 0;
static final int MOUSE_BUTTON_LEFT = 1;
static final int MOUSE_BUTTON_MIDDLE = 2;
@ -1130,7 +1130,7 @@ public class VncCanvas extends AppCompatImageView {
boolean down = (evt.getAction() == KeyEvent.ACTION_DOWN);
int key;
int metaState = evt.getMetaState();
//metaState = 0;
metaState = 0;
// Log.v("Key Pressed", keyCode + ", metaState = " + metaState);
switch (keyCode) {
@ -1207,11 +1207,6 @@ public class VncCanvas extends AppCompatImageView {
break;
}
if ((evt.getMetaState() & KeyEvent.META_META_ON) == KeyEvent.META_META_ON) {
// Log.v("meta", "setting meta mask");
metaState = metaState | VncCanvas.META_MASK;
}
if ((evt.getMetaState() & KeyEvent.META_CTRL_ON) == KeyEvent.META_CTRL_ON) {
// Log.v("meta", "setting ctrl mask");
metaState = metaState | VncCanvas.CTRL_MASK;
@ -1237,7 +1232,7 @@ public class VncCanvas extends AppCompatImageView {
lastKeyDown = key;
}
rfb.writeKeyEvent(key, metaStateCollector > 0 ? metaStateCollector : metaState, down);
rfb.writeKeyEvent(key, metaState, down);
this.ALT_PRESSED = false;
} catch (Exception e) {
Log.e(TAG, "processLocalKeyEvent: ", e);
@ -1254,15 +1249,10 @@ public class VncCanvas extends AppCompatImageView {
}
}
public int metaStateCollector = 0;
public void sendMetaKey1(int key, int flags) {
try {
rfb.writeKeyEvent(key, flags, true);
rfb.writeKeyEvent(key, flags, false);
VncCanvasActivity activity = (VncCanvasActivity) VncCanvas.this.getContext();
activity.onKeyChanged(key, false, flags);
} catch (IOException ioe) {
Log.e(TAG, "sendMetaKey1: ", ioe);
}
@ -1272,9 +1262,6 @@ public class VncCanvas extends AppCompatImageView {
public void sendMetaKey1Down(int key, int flags) {
try {
rfb.writeKeyEvent(key, flags, true);
VncCanvasActivity activity = (VncCanvasActivity) VncCanvas.this.getContext();
activity.onKeyChanged(key, true, flags);
} catch (IOException ioe) {
Log.e(TAG, "sendMetaKey1Down: ", ioe);
}
@ -1284,9 +1271,6 @@ public class VncCanvas extends AppCompatImageView {
public void sendMetaKey1Up(int key, int flags) {
try {
rfb.writeKeyEvent(key, flags, false);
VncCanvasActivity activity = (VncCanvasActivity) VncCanvas.this.getContext();
activity.onKeyChanged(key, false, flags);
} catch (IOException ioe) {
Log.e(TAG, "sendMetaKey1Up: ", ioe);
}
@ -1347,12 +1331,11 @@ public class VncCanvas extends AppCompatImageView {
}
private static final int LEFT_SHIFT_KEY_CODE = 0xFFE1;
public void sendText(String s) {
int l = s.length();
for (int i = 0; i < l; i++) {
char c = s.charAt(i);
int meta = 0;
int keysym = c;
if (Character.isISOControl(c)) {
if (c == '\n') {
@ -1361,27 +1344,13 @@ public class VncCanvas extends AppCompatImageView {
continue;
}
}
boolean isNeedShift = Character.isUpperCase(c) || isSpecialKey(c) > -1;
try {
if (isNeedShift) {
rfb.writeKeyEvent(LEFT_SHIFT_KEY_CODE, 0, true);
}
rfb.writeKeyEvent(keysym, 0, true);
rfb.writeKeyEvent(keysym, 0, false);
if (isNeedShift) {
rfb.writeKeyEvent(LEFT_SHIFT_KEY_CODE, 0, false);
}
rfb.writeKeyEvent(keysym, meta, true);
rfb.writeKeyEvent(keysym, meta, false);
} catch (IOException ioe) {
Log.e(TAG, "sendText: ",ioe);
}
}
VncCanvasActivity activity = (VncCanvasActivity) VncCanvas.this.getContext();
activity.onKeyChanged(-1, false, -1);
}
void sendMetaKey(MetaKeyBean meta) {

View file

@ -1179,7 +1179,6 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
boolean defaultKeyDownHandler(int keyCode, KeyEvent evt) {
if (vncCanvas.processLocalKeyEvent(keyCode, evt)) {
onKeyChanged(keyCode, true, -1);
return true;
}
return super.onKeyDown(keyCode, evt);
@ -1187,7 +1186,6 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
boolean defaultKeyUpHandler(int keyCode, KeyEvent evt) {
if (vncCanvas.processLocalKeyEvent(keyCode, evt)) {
onKeyChanged(keyCode, false, -1);
return true;
}
return super.onKeyUp(keyCode, evt);
@ -1818,10 +1816,6 @@ public abstract class VncCanvasActivity extends AppCompatActivity {
}
public void onKeyChanged(int key, boolean isDown, int flags) {
}
public void reconnect() {
// Recreate canvas to change resolution as resolution when changed in some Linux OS may cause canvas to not resize accordingly.

View file

@ -1188,18 +1188,6 @@ public class MainSettingsManager extends AppCompatActivity
return prefs.getInt("standardSetupVersion", 0);
}
public static void setCoreSetupVersion(Context context, int value) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putInt("coreSetupVersion", value);
edit.apply();
}
public static int getCoreSetupVersion(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getInt("coreSetupVersion", 0);
}
public static void setShowLastCrashLog(Context context, Boolean _boolean) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
@ -1341,18 +1329,6 @@ public class MainSettingsManager extends AppCompatActivity
public static Boolean getAutoSwitchToExternalMouse(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean("autoSwitchToExternalMouse", false);
}
public static void setBuiltInFilePicker(Context context, Boolean _boolean) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("builtInFilePicker", _boolean);
edit.apply();
}
public static Boolean getBuiltInFilePicker(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean("builtInFilePicker", false);
return prefs.getBoolean("autoSwitchToExternalMouse", true);
}
}

View file

@ -65,7 +65,6 @@ import com.vectras.vm.databinding.DesktopControlsBinding;
import com.vectras.vm.databinding.GameControlsBinding;
import com.vectras.vm.databinding.SendKeyDialogBinding;
import com.vectras.vm.manager.QmpSender;
import com.vectras.vm.manager.VNCKeyManager;
import com.vectras.vm.manager.VmAudioManager;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.manager.VmControllerDialog;
@ -74,7 +73,7 @@ import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.ListUtils;
import com.vectras.vm.utils.SimulateKeyEvent;
import com.vectras.vm.sound.StreamAudio;
import com.vectras.vm.utils.StreamAudio;
import com.vectras.vm.utils.UIUtils;
import com.vectras.vm.view.DynamicBubble;
@ -114,6 +113,8 @@ public class MainVNCActivity extends VncCanvasActivity {
String[] functionsArray = {"F1", "F2", "F3", "F4",
"F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"};
public boolean ctrlClicked = false;
public boolean altClicked = false;
private final ArrayList<HashMap<String, Object>> listmapForSendKey = new ArrayList<>();
private boolean isConnected = false;
@ -123,8 +124,6 @@ public class MainVNCActivity extends VncCanvasActivity {
private boolean isScaling = false;
private boolean isPinchToZoom;
VNCKeyManager vncKeyManager;
private InputManager inputManager;
private final InputManager.InputDeviceListener inputDeviceListener =
@ -398,7 +397,7 @@ public class MainVNCActivity extends VncCanvasActivity {
public void onDestroy() {
super.onDestroy();
this.stopTimeListener();
if (streamAudio != null) streamAudio.release();
if (streamAudio != null) streamAudio.stop();
//Terminal.killQemuProcess();
}
@ -775,14 +774,8 @@ public class MainVNCActivity extends VncCanvasActivity {
} catch (InterruptedException e) {
Log.e(TAG, "onMonitor: ", e);
}
try {
vncCanvas.sendMetaKey1(50, 6);
monitorMode = true;
} catch (NullPointerException e) {
monitorMode = false;
Log.e(TAG, "onMonitor: ", e);
}
monitorMode = true;
vncCanvas.sendMetaKey1(50, 6);
});
t.start();
@ -887,11 +880,6 @@ public class MainVNCActivity extends VncCanvasActivity {
}
}
@Override
public void onKeyChanged(int key, boolean isDown, int flags) {
if (vncKeyManager != null) vncKeyManager.onKeyChanged(key, isDown, flags);
}
@Override
public void onConnected() {
runOnUiThread(() -> {
@ -931,9 +919,6 @@ public class MainVNCActivity extends VncCanvasActivity {
}
firstConnection = true;
vncKeyManager = new VNCKeyManager(vncCanvas);
vncKeyManager.setButtons(null, bindingDesktopControls.ctrlBtn, bindingDesktopControls.altBtn, bindingDesktopControls.winBtn);
});
}
@ -956,8 +941,6 @@ public class MainVNCActivity extends VncCanvasActivity {
MainSettingsManager.getAutoSwitchToExternalMouse(this) &&
Config.mouseMode == Config.MouseMode.External)
setUIModeMobile(false);
if (vncKeyManager != null) vncKeyManager.reset();
});
}
@ -1260,17 +1243,39 @@ public class MainVNCActivity extends VncCanvasActivity {
bindingDesktopControls.enterBtn.setOnClickListener(v -> simulateKeyPress(KeyEvent.KEYCODE_ENTER));
bindingDesktopControls.ctrlBtn.setOnClickListener(v -> {
if (vncKeyManager != null) vncKeyManager.ctrlKey();
bindingDesktopControls.ctrlBtn.setOnClickListener(new View.OnClickListener() {
@SuppressLint("UseCompatLoadingForDrawables")
@Override
public void onClick(View v) {
if (!ctrlClicked) {
sendKey(KeyEvent.KEYCODE_CTRL_LEFT, false);
bindingDesktopControls.ctrlBtn.setBackgroundResource(R.drawable.controls_button2);
ctrlClicked = true;
} else {
sendKey(KeyEvent.KEYCODE_CTRL_LEFT, true);
bindingDesktopControls.ctrlBtn.setBackgroundResource(R.drawable.controls_button1);
ctrlClicked = false;
}
}
});
bindingDesktopControls.altBtn.setOnClickListener(v -> {
if (vncKeyManager != null) vncKeyManager.altKey();
bindingDesktopControls.altBtn.setOnClickListener(new View.OnClickListener() {
@SuppressLint("UseCompatLoadingForDrawables")
@Override
public void onClick(View v) {
if (!altClicked) {
sendKey(KeyEvent.KEYCODE_ALT_LEFT, false);
bindingDesktopControls.altBtn.setBackgroundResource(R.drawable.controls_button2);
altClicked = true;
} else {
sendKey(KeyEvent.KEYCODE_ALT_LEFT, true);
bindingDesktopControls.altBtn.setBackgroundResource(R.drawable.controls_button1);
altClicked = false;
}
}
});
bindingDesktopControls.delBtn.setOnClickListener(v -> {
if (vncKeyManager != null) vncKeyManager.deleteKey();
});
bindingDesktopControls.delBtn.setOnClickListener(v -> simulateKeyPress(KeyEvent.KEYCODE_DEL));
bindingControls.btnQmp.setOnClickListener(v -> {
if (monitorMode) {
@ -1316,7 +1321,10 @@ public class MainVNCActivity extends VncCanvasActivity {
});
bindingDesktopControls.winBtn.setOnClickListener(v -> {
if (vncKeyManager != null) vncKeyManager.winKey();
sendKey(KeyEvent.KEYCODE_CTRL_LEFT, false);
sendKey(KeyEvent.KEYCODE_ESCAPE, false);
sendKey(KeyEvent.KEYCODE_CTRL_LEFT, false);
sendKey(KeyEvent.KEYCODE_ESCAPE, false);
});
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
@ -1465,9 +1473,8 @@ public class MainVNCActivity extends VncCanvasActivity {
});
bindingSendKey.sendtextButton.setOnClickListener(v -> {
String text = bindingSendKey.sendtextEdittext.getText().toString();
vncCanvas.sendText(bindingSendKey.sendtextEdittext.getText().toString());
bindingSendKey.sendtextEdittext.setText("");
new Thread(() -> vncCanvas.sendText(text)).start();
});
bindingSendKey.sendtextEdittext.addTextChangedListener(new TextWatcher() {
@ -1552,11 +1559,6 @@ public class MainVNCActivity extends VncCanvasActivity {
_all.setOnClickListener(_view1 -> {
if (_position == 0) {
sendCtrlAtlDelKey();
} else if (_position == 2) {
if (vncKeyManager != null) {
vncKeyManager.winKey();
new Handler(Looper.getMainLooper()).postDelayed(() -> vncKeyManager.winKey(), 100);
}
} else {
Boolean useKeyEvent = (Boolean) _data.get(_position).get("useKeyEvent");
Boolean sendWithQMP = (Boolean) _data.get(_position).get("useQMP");

View file

@ -8,7 +8,6 @@ import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity;
import com.vectras.vm.adapters.GithubUserAdapter;
import com.vectras.vm.utils.CommandUtils;
import com.vectras.vm.utils.UIUtils;
@ -95,14 +94,12 @@ public class AboutActivity extends AppCompatActivity implements View.OnClickList
TextView qemuVersion = findViewById(R.id.qemuVersion);
executor.execute(() -> {
String qemuVersionName = CommandUtils.getQemuVersionName(this);
String qemuVersionName = CommandUtils.getQemuVersionName();
runOnUiThread(() -> {
if (!qemuVersionName.isEmpty()) qemuVersion.setText(qemuVersionName); else getString(R.string.unknow);
});
});
findViewById(R.id.btn_open_source_licenses).setOnClickListener(v -> startActivity(new Intent(this, OssLicensesMenuActivity.class)));
}
@Override

View file

@ -19,7 +19,6 @@ public class AppConfig {
public static String vectrasVersion;
public static int vectrasVersionCode;
public static final int standardSetupVersion = 922202606;
public static final int coreSetupVersion = 0;
public static String vectrasWebsite = "https://vectras.vercel.app/";
public static String vectrasWebsiteRaw = "https://raw.githubusercontent.com/AnBui2004/Vectras-VM-Emu-Android/refs/heads/master/web/";
public static String bootstrapfileslink = vectrasWebsiteRaw + "/data/setupfiles3.json";
@ -79,13 +78,13 @@ public class AppConfig {
public static String neededPkgs() {
if (DeviceUtils.isArm()) {
return "sudo bash aria2 tar dwm xterm libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +
return "bash aria2 tar dwm xterm libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +
" libusbredirparser usbredir-dev sdl2 sdl2-dev sdl2_image-dev libepoxy-dev virglrenderer-dev rdma-core fluxbox" +
" libusb libaio ncurses-libs curl libnfs gtk+3.0 gtk+3.0-dev fuse libpulse libseccomp jack pipewire liburing pulseaudio pulseaudio-alsa alsa-plugins-pulse" +
" mesa-dri-gallium mesa-vulkan-swrast vulkan-loader mesa-utils mesa-egl mesa-gbm mesa-vulkan-ati mesa-vulkan-broadcom mesa-vulkan-freedreno mesa-vulkan-panfrost" +
" qemu-audio-sdl capstone libcbor snappy lzo ndctl keyutils-libs vde2-libs libdw libbpf sndio-libs linux-pam fuse3-libs libssh vte3 iasl perl";
} else {
return "sudo bash aria2 tar dwm xterm libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +
return "bash aria2 tar dwm xterm libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +
" libusbredirparser usbredir-dev sdl2 sdl2-dev sdl2_image-dev libepoxy-dev virglrenderer-dev rdma-core fluxbox" +
" libusb libaio ncurses-libs curl libnfs gtk+3.0 gtk+3.0-dev fuse libpulse libseccomp jack pipewire liburing pulseaudio pulseaudio-alsa alsa-plugins-pulse" +
" mesa-dri-gallium mesa-vulkan-swrast vulkan-loader mesa-utils mesa-egl" +
@ -95,13 +94,13 @@ public class AppConfig {
public static String neededPkgs32bit() {
if (DeviceUtils.isArm()) {
return "sudo bash aria2 tar dwm xterm libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +
return "bash aria2 tar dwm xterm libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +
" libusbredirparser usbredir-dev sdl2 sdl2-dev sdl2_image-dev libepoxy-dev virglrenderer-dev rdma-core fluxbox" +
" libusb libaio ncurses-libs curl libnfs gtk+3.0 gtk+3.0-dev fuse libpulse libseccomp jack pipewire liburing pulseaudio pulseaudio-alsa alsa-plugins-pulse" +
" mesa-dri-gallium mesa-vulkan-swrast vulkan-loader mesa-utils mesa-egl" +
" qemu-audio-sdl capstone libcbor snappy lzo ndctl keyutils-libs vde2-libs libdw libbpf sndio-libs linux-pam fuse3-libs libssh vte3 iasl perl";
} else {
return "sudo bash aria2 tar dwm xterm libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +
return "bash aria2 tar dwm xterm libslirp libslirp-dev pulseaudio-dev glib-dev pixman-dev zlib-dev spice-dev" +
" libusbredirparser usbredir-dev sdl2 sdl2-dev sdl2_image-dev libepoxy-dev virglrenderer-dev rdma-core fluxbox" +
" libusb libaio ncurses-libs curl libnfs gtk+3.0 gtk+3.0-dev fuse libpulse libseccomp jack pipewire liburing pulseaudio pulseaudio-alsa alsa-plugins-pulse" +
" mesa-dri-gallium mesa-vulkan-swrast vulkan-loader mesa-utils mesa-egl" +
@ -120,5 +119,4 @@ public class AppConfig {
public static String virtIOWinUrl = "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.285-1/virtio-win.iso";
public static String virtIOWinUrlMd5 = "9e650d0e7c6e017a91ca299c8f7ed766";
public static boolean isGmsAvailable = false;
}

View file

@ -168,7 +168,6 @@ public class ExportRomActivity extends AppCompatActivity {
vmConfigMap.put("fdb", "");
}
vmConfigMap.put("networkCard", current.networkCard);
vmConfigMap.put("sharedFolder", current.sharedFolder);
vmConfigMap.put("bootFrom", current.bootFrom);
vmConfigMap.put("isShowBootMenu", current.isShowBootMenu);

View file

@ -23,7 +23,7 @@ import com.vectras.vm.R;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.ProgressDialog;
import com.vectras.vterm.Terminal2;
import com.vectras.vterm.Terminal;
import java.io.File;
import java.util.Objects;
@ -99,8 +99,8 @@ public class CreateImageDialogFragment extends DialogFragment {
progressDialog.show();
new Thread(() -> {
String result = new Terminal2(requireContext()).executeOnThisThread("qemu-img create -f qcow2 \"" + folder + Objects.requireNonNull(imageName.getText()) + ".qcow2\" " +
Objects.requireNonNull(imageSize.getText()) + "G").trim();
String result = Terminal.executeShellCommandWithResult("qemu-img create -f qcow2 \"" + folder + Objects.requireNonNull(imageName.getText()) + ".qcow2\" " +
Objects.requireNonNull(imageSize.getText()) + "G", requireActivity()).trim();
if (isMarkPendingAdd) VmFileManager.markPendingAdd(folder + Objects.requireNonNull(imageName.getText()) + ".qcow2");
requireActivity().runOnUiThread(() -> {

View file

@ -1,6 +1,5 @@
package com.vectras.vm;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@ -9,28 +8,21 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import com.vectras.vm.main.core.MainStartVM;
import com.vectras.vm.manager.VmServiceManager;
import com.vectras.vm.utils.ClipboardUltils;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vterm.Terminal;
import com.vectras.vterm.Terminal2;
import java.util.Objects;
public class MainService extends Service {
public static String CHANNEL_ID = "Vectras VM Service";
private final int NOTIFICATION_ID = 1;
public static String vmName = "Vectras VM";
private final String MACHINE_NAME = "Vectras VM";
public static String env = null;
private static String TAG = "MainService";
private String TAG = "MainService";
public static MainService service;
public static Context activityContext;
@ -50,7 +42,7 @@ public class MainService extends Service {
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText("The virtual machines are running...")
.setContentText(MACHINE_NAME + " running in background.")
.setSmallIcon(R.drawable.ic_vectras_vm_48)
.addAction(R.drawable.close_24px, getString(R.string.stop), pStopSelf)
.build();
@ -59,7 +51,8 @@ public class MainService extends Service {
if (env != null) {
if (service != null) {
startCommand(vmName, env, activityContext);
Terminal vterm = new Terminal(activityContext);
vterm.executeShellCommand2(env, true, activityContext);
}
} else {
Log.e(TAG, "env is null");
@ -79,13 +72,10 @@ public class MainService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && Objects.equals(intent.getAction(), STOP_ACTION)) {
new Thread(() -> {
VMManager.killallqemuprocesses(this);
new Handler(Looper.getMainLooper()).post(() -> {
stopForeground(true);
stopSelf();
});
}).start();
VMManager.killallqemuprocesses(this);
stopForeground(true);
stopSelf();
return START_NOT_STICKY;
}
return START_NOT_STICKY;
}
@ -107,55 +97,8 @@ public class MainService extends Service {
}
}
public static void startCommand(String vmName, String env, Context context) {
Terminal2 terminal2 = new Terminal2(activityContext);
terminal2.setDefaultShellBash();
terminal2.setStartup("export XDG_RUNTIME_DIR=/tmp && unset PULSE_SERVER");
terminal2.execute(env, new Terminal2.Terminal2Callback() {
@Override
public void onRunning(String command, String newLine) {
// Nothing to do.
}
@Override
public void onFinished(String command, String log, int status) {
if (context instanceof Activity activity) {
if (activity.isFinishing() || activity.isDestroyed()) {
return;
}
} else {
Log.e(TAG, "context is not an Activity");
return;
}
if (!(log.trim().isEmpty() || log.trim().equals(MainStartVM.TAG_FINISHED_WITHOUT_ERROR))) {
new Handler(Looper.getMainLooper()).post(() -> {
if (!VMManager.isExecutedCommandError(command, log, context)) {
String finalLog = log.contains(MainStartVM.TAG_FINISHED_WITHOUT_ERROR) ? log.substring(0, log.lastIndexOf(MainStartVM.TAG_FINISHED_WITHOUT_ERROR) - 1) : log;
DialogUtils.twoDialog(context, vmName, finalLog, context.getString(R.string.copy), context.getString(R.string.close), true, R.drawable.stack_24px, true,
() -> ClipboardUltils.copyToClipboard(context, log), null, null);
}
});
}
VmServiceManager.stopService(context);
}
@Override
public void onError(String command, Exception exception) {
if (context instanceof Activity activity) {
if (activity.isFinishing() || activity.isDestroyed()) {
return;
}
} else {
Log.e(TAG, "context is not an Activity");
return;
}
new Handler(Looper.getMainLooper()).post(() -> DialogUtils.twoDialog(context, "Execution Result", exception.getMessage(), context.getString(R.string.copy), context.getString(R.string.close), true, R.drawable.round_terminal_24, true,
() -> ClipboardUltils.copyToClipboard(context, exception.getMessage()), null, null));
}
});
public static void startCommand(String _env, Context _context) {
Terminal vterm = new Terminal(_context);
vterm.executeShellCommand2(_env, true, _context);
}
}

View file

@ -126,12 +126,7 @@ public class SplashActivity extends AppCompatActivity {
if (MainSettingsManager.getShowLastCrashLog(this)) {
startActivity(new Intent(this, LastCrashActivity.class));
} else if (SetupFeatureCore.isInstalledQemu(this)) {
if (MainSettingsManager.getCoreSetupVersion(this) != AppConfig.coreSetupVersion) {
Intent intent = new Intent();
intent.putExtra("action", SetupWizard2Activity.ACTION_CORE_SYSTEM_UPDATE);
intent.setClass(this, SetupWizard2Activity.class);
startActivity(intent);
} else if (MainSettingsManager.getStandardSetupVersion(this) != AppConfig.standardSetupVersion &&
if (MainSettingsManager.getStandardSetupVersion(this) != AppConfig.standardSetupVersion &&
!MainSettingsManager.getsetUpWithManualSetupBefore(this)) {
Intent intent = new Intent();
intent.putExtra("action", SetupWizard2Activity.ACTION_SYSTEM_UPDATE);

View file

@ -7,7 +7,7 @@ import android.util.Log;
import com.vectras.qemu.Config;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.qemu.utils.RamInfo;
import com.vectras.vm.creator.utils.VMCreatorSelector;
import com.vectras.vm.creator.VMCreatorSelector;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.manager.BatteryEmulatorManager;
import com.vectras.vm.manager.FirmwareManager;
@ -15,6 +15,7 @@ import com.vectras.vm.manager.ParamManager;
import com.vectras.vm.manager.QemuManager;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.settings.ItemSettingsSelector;
import com.vectras.vm.setupwizard.SetupFeatureCore;
import com.vectras.vm.utils.CpuHelper;
import com.vectras.vm.utils.DeviceUtils;
import com.vectras.vm.utils.FileUtils;
@ -51,75 +52,26 @@ public class StartVM {
String extraParams = vmData.itemExtra;
String machineParams = "";
if (!ParamManager.hasMachine(extraParams)) {
String machine = Objects.requireNonNull(VMCreatorSelector.getMachine(activity, MainSettingsManager.getArch(activity), vmData.machine).get("value")).toString();
if (!machine.isEmpty()) {
machineParams = "-M " + machine;
}
if (
vmConfigs.nvirt &&
!MainSettingsManager.getArch(activity).equals(MainSettingsManager.PPC_ARCH) &&
MainSettingsManager.getArch(activity).equals(MainSettingsManager.ARM64_ARCH)
) {
machineParams += ",virtualization=true";
}
machineParams += " ";
}
String cpuParams = "";
if (!ParamManager.hasCpu(extraParams)) {
String cpu = Objects.requireNonNull(VMCreatorSelector.getCpu(activity, MainSettingsManager.getArch(activity), vmData.cpu).get("value")).toString();
String flags = "";
if (
vmConfigs.nvirt &&
(
MainSettingsManager.getArch(activity).equals(MainSettingsManager.X86_64_ARCH) ||
MainSettingsManager.getArch(activity).equals(MainSettingsManager.I386_ARCH)
)
) {
flags += ",+vmx,+svm";
}
String cpu = Objects.requireNonNull(VMCreatorSelector.getCpu(activity, MainSettingsManager.getArch(activity), vmData.cpu).get("value")).toString();
if (!cpu.isEmpty() && !extraParams.contains("-cpu ")) {
cpuParams = " -cpu " + cpu;
}
if (!flags.isEmpty() && cpu.isEmpty()) {
if (MainSettingsManager.getArch(activity).equals(MainSettingsManager.X86_64_ARCH)) {
cpu = "qemu64";
} else if (MainSettingsManager.getArch(activity).equals(MainSettingsManager.I386_ARCH)) {
cpu = "qemu32";
}
}
CpuHelper cpuHelper = new CpuHelper();
if (!cpu.isEmpty()) {
cpuParams = " -cpu " + cpu + flags;
int cores = Integer.parseInt(Objects.requireNonNull(VMCreatorSelector.getCpuCore(MainSettingsManager.getArch(activity), vmConfigs.cores).get("value")).toString());
int threads = Math.max(1, vmConfigs.threads + 1);
if (!extraParams.contains("-smp ")) {
if (cores * threads > cpuHelper.getCpuThreads()) {
cpuParams += " -smp sockets=1,cores=" + cpuHelper.getCpuCores() + ",threads=1";
} else {
cpuParams += " -smp sockets=1,cores=" + cores + ",threads=" + threads;
}
}
if (!ParamManager.hasSmp(extraParams)) {
CpuHelper cpuHelper = new CpuHelper();
int cores = Integer.parseInt(Objects.requireNonNull(VMCreatorSelector.getCpuCore(MainSettingsManager.getArch(activity), vmConfigs.cores).get("value")).toString());
int threads = Math.max(1, vmConfigs.threads + 1);
if (!extraParams.contains("-smp ")) {
if (cores * threads > cpuHelper.getCpuThreads()) {
cpuParams += " -smp sockets=1,cores=" + cpuHelper.getCpuCores() + ",threads=1";
} else {
cpuParams += " -smp sockets=1,cores=" + cores + ",threads=" + threads;
}
}
}
if (!cpuParams.isEmpty()) cpuParams += " ";
String networkParams = "";
String network = Objects.requireNonNull(VMCreatorSelector.getNetworkCard(activity, vmData.networkCard).get("value")).toString();
if (!network.isEmpty()) {
networkParams = " -device " + network + ",netdev=net0 -netdev user,id=net0";
}
if (!cpuParams.isEmpty()) extraParams = cpuParams + " " + extraParams;
String bootFromParams = Objects.requireNonNull(VMCreatorSelector.getBootFrom(activity, vmData.bootFrom).get("value")).toString();
String showBootMenuParams = vmData.isShowBootMenu ? "menu=on" : "";
@ -128,7 +80,7 @@ public class StartVM {
bootParams = "-boot " + bootFromParams + (!bootFromParams.isEmpty() && !showBootMenuParams.isEmpty() ? "," : "") + showBootMenuParams + " ";
}
extraParams = machineParams + cpuParams + bootParams + networkParams + " " + extraParams;
extraParams = bootParams + extraParams;
return env(activity, extraParams, vmData.itemPath, false);
}
@ -334,14 +286,14 @@ public class StartVM {
extractFirmware(activity);
}
// String machine = "-M ";
// if (Objects.equals(MainSettingsManager.getArch(activity), "X86_64")) {
// machine += "pc";
// params.add(machine);
// } else if (Objects.equals(MainSettingsManager.getArch(activity), "ARM64")) {
// machine += "virt";
// params.add(machine);
// }
String machine = "-M ";
if (Objects.equals(MainSettingsManager.getArch(activity), "X86_64")) {
machine += "pc";
params.add(machine);
} else if (Objects.equals(MainSettingsManager.getArch(activity), "ARM64")) {
machine += "virt";
params.add(machine);
}
if (MainSettingsManager.useMemoryOvercommit(activity)) {
params.add("-overcommit");

View file

@ -19,7 +19,6 @@ import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.vectras.qemu.Config;
import com.vectras.qemu.MainSettingsManager;
@ -38,7 +37,6 @@ import com.vectras.vm.utils.JSONUtils;
import com.vectras.vm.utils.ProgressDialog;
import com.vectras.vm.utils.TextUtils;
import com.vectras.vterm.Terminal;
import com.vectras.vterm.Terminal2;
import org.jetbrains.annotations.Contract;
@ -72,14 +70,8 @@ public class VMManager {
if (!JSONUtils.isValidFromString(vmJsonListContent) || vmId.isEmpty()) return false;
ArrayList<HashMap<String, Object>> vmList;
try {
vmList = new Gson().fromJson(vmJsonListContent, new TypeToken<ArrayList<HashMap<String, Object>>>() {
}.getType());
} catch (JsonSyntaxException e) {
return JSONUtils.isValidFromFile(VmFileManager.getConfigFile(vmId));
}
ArrayList<HashMap<String, Object>> vmList = new Gson().fromJson(vmJsonListContent, new TypeToken<ArrayList<HashMap<String, Object>>>() {
}.getType());
if (vmList == null) return false;
@ -666,6 +658,8 @@ public class VMManager {
return false;
}
VmServiceManager.stopService(_activity);
if (_command.contains("qemu-system") && _result.contains("Killed")) {
isQemuStopedWithError = true;
return true;
@ -733,7 +727,7 @@ public class VMManager {
},
null, null);
return false;
} else if (!_result.contains(MainStartVM.TAG_FINISHED_WITHOUT_ERROR)) {
} else if (_command.contains("qemu-system") && _result.contains("qemu-system") && !_result.contains("warning:")) {
//Error code: UNKNOW_ERROR
DialogUtils.oneDialog(_activity, _activity.getString(R.string.problem_has_been_detected), _activity.getString(R.string.vm_could_not_be_run_content) + "\n\n" + _result, R.drawable.error_96px);
_activity.stopService(new Intent(_activity, MainService.class));
@ -847,7 +841,7 @@ public class VMManager {
}
public static boolean isVMRunning(Context context, String vmID) {
String result = new Terminal2(context).executeOnThisThread("ps -e");
String result = Terminal.executeShellCommandWithResult("ps -e", context);
if (result.contains(" -qmp unix:" + Config.getLocalQMPSocketPath(vmID))) {
Log.d("VMManager.isThisVMRunning", "Yes.\n\n" + result);
return true;
@ -864,6 +858,18 @@ public class VMManager {
return exists;
}
public static boolean isQemuRunning(Activity activity) {
Terminal vterm = new Terminal(activity);
vterm.executeShellCommand2("ps -e", false, activity);
if (AppConfig.temporaryLastedTerminalOutput.contains("qemu-system")) {
Log.d("VMManager.isQemuRunning", "Yes");
return true;
} else {
Log.d("VMManager.isQemuRunning", "No");
return false;
}
}
public static boolean isHaveADisk(String env) {
return env.contains("-drive") || env.contains("-hda") || env.contains("-hdb") || env.contains("-cdrom") || env.contains("-fda") || env.contains("-fdb");
}
@ -896,8 +902,20 @@ public class VMManager {
}, null, null);
}
public static void killcurrentqemuprocess(Activity activity) {
Terminal vterm = new Terminal(activity);
String qemuProcess = switch (MainSettingsManager.getArch(activity)) {
case "ARM64" -> "qemu-system-aarch64";
case "PPC" -> "qemu-system-ppc";
case "I386" -> "qemu-system-i386";
default -> "qemu-system-x86_64";
};
vterm.executeShellCommand2("killall -15 " + qemuProcess + "; sleep 1; killall -9 " + qemuProcess, false, null);
}
public static void killallqemuprocesses(Context context) {
new Terminal2(context).executeOnThisThread("pkill -15 -f qemu-system-; sleep 1; pkill -9 -f qemu-system-");
Terminal vterm = new Terminal(context);
vterm.executeShellCommand2("pkill -15 -f qemu-system-; sleep 1; pkill -9 -f qemu-system-", false, null);
}
public static String startMigrate() {

View file

@ -19,11 +19,11 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics;
import com.vectras.qemu.Config;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.GmsChecker;
import com.vectras.vm.utils.PackageUtils;
import com.vectras.vm.utils.UIUtils;
import java.lang.ref.WeakReference;
import java.util.Locale;
public class VectrasApp extends Application {
public static VectrasApp vectrasapp;
@ -97,14 +97,8 @@ public class VectrasApp extends Application {
}
});
FirebaseAnalytics.getInstance(this).logEvent(FirebaseAnalytics.Event.APP_OPEN, null);
FirebaseCrashlytics.getInstance().log("App started: " + AppConfig.vectrasVersion);
if (GmsChecker.isAvailable(this)) {
AppConfig.isGmsAvailable = true;
FirebaseAnalytics.getInstance(this).logEvent(FirebaseAnalytics.Event.APP_OPEN, null);
} else {
FirebaseCrashlytics.getInstance().log("Device does not support GMS.");
}
}
private void setupTheme() {

View file

@ -1,4 +1,4 @@
package com.vectras.vm.creator.configs;
package com.vectras.vm.creator;
import android.content.Context;
@ -145,61 +145,4 @@ public class ListManager {
return list;
}
public static ArrayList<HashMap<String, Object>> machines(Context context, String arch) {
return switch (arch) {
case MainSettingsManager.ARM64_ARCH -> machinesArm64(context);
case MainSettingsManager.PPC_ARCH -> machinesPpc(context);
default -> machinesX8664(context);
};
}
public static ArrayList<HashMap<String, Object>> machinesX8664(Context context) {
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
UniversalPickerDialog.putToList(list, context.getString(R.string.defaulttext), "");
UniversalPickerDialog.putToList(list, context.getString(R.string.i440fx), "pc");
UniversalPickerDialog.putToList(list, context.getString(R.string.q35), "q35");
return list;
}
public static ArrayList<HashMap<String, Object>> machinesArm64(Context context) {
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
UniversalPickerDialog.putToList(list, context.getString(R.string.virt), "virt");
return list;
}
public static ArrayList<HashMap<String, Object>> machinesPpc(Context context) {
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
UniversalPickerDialog.putToList(list, context.getString(R.string.defaulttext), "");
UniversalPickerDialog.putToList(list, context.getString(R.string.mac99), "mac99");
UniversalPickerDialog.putToList(list, context.getString(R.string.g3beige), "g3beige");
UniversalPickerDialog.putToList(list, context.getString(R.string.pegasos2), "pegasos2");
UniversalPickerDialog.putToList(list, context.getString(R.string.amigaone), "amigaone");
UniversalPickerDialog.putToList(list, context.getString(R.string.sam460ex), "sam460ex");
return list;
}
public static ArrayList<HashMap<String, Object>> networkCards(Context context) {
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
UniversalPickerDialog.putToList(list, context.getString(R.string.none), "");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_e1000e_82574l), "e1000e");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_igb_82576), "igb");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_e1000_82540em), "e1000");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_e1000_82545em), "e1000-82545em");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_e1000_82544gc), "e1000-82544gc");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82801), "i82801");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82562), "i82562");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82559er), "i82559er");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82558b), "i82558b");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82557c), "i82557c");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82551), "i82551");
UniversalPickerDialog.putToList(list, context.getString(R.string.intel_i82550), "i82550");
UniversalPickerDialog.putToList(list, context.getString(R.string.realtek_rtl8139), "rtl8139");
UniversalPickerDialog.putToList(list, context.getString(R.string.amd_pcnet), "pcnet");
UniversalPickerDialog.putToList(list, context.getString(R.string.novell_ne2000), "ne2k_pci");
UniversalPickerDialog.putToList(list, context.getString(R.string.vmware_vmxnet3), "vmxnet3");
UniversalPickerDialog.putToList(list, context.getString(R.string.virtio_net), "virtio-net-pci");
UniversalPickerDialog.putToList(list, context.getString(R.string.virtio_net_transitional), "virtio-net-pci-transitional");
return list;
}
}

View file

@ -1,14 +1,27 @@
package com.vectras.vm.creator.utils;
package com.vectras.vm.creator;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.color.MaterialColors;
import com.vectras.vm.R;
import com.vectras.vm.creator.configs.ListManager;
import com.vectras.vm.databinding.DialogListSelectorLayoutBinding;
import com.vectras.vm.databinding.SimpleLayoutListViewWithCheckBinding;
import com.vectras.vm.utils.UniversalPickerDialog;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
public class VMCreatorSelector {
private static final String TAG = "VMCreatorSelector";
@ -41,23 +54,6 @@ public class VMCreatorSelector {
showDialog(activity, ListManager.threads(arch), position, callback, activity.getString(R.string.thread));
}
public static HashMap<String, Object> getMachine(Context context, String arch, int position) {
ArrayList<HashMap<String, Object>> list = ListManager.machines(context, arch);
return list.get(position < 0 ? 0 : Math.min(position, list.size() - 1));
}
public static void machine(Activity activity, String arch, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback) {
showDialog(activity, ListManager.machines(activity, arch), position, callback, activity.getString(R.string.machine));
}
public static void networkCard(Activity activity, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback) {
showDialog(activity, ListManager.networkCards(activity), position, callback, activity.getString(R.string.network_card));
}
public static HashMap<String, Object> getNetworkCard(Context context, int position) {
return ListManager.networkCards(context).get(position);
}
public static HashMap<String, Object> getBootFrom(Context context, int position) {
return ListManager.bootFrom(context).get(position);
}

View file

@ -1,125 +0,0 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.vm.R;
import com.vectras.vm.creator.QemuParamsEditorActivity;
import com.vectras.vm.creator.utils.EditorUtils;
import com.vectras.vm.databinding.CreatorAdvancedDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.utils.DialogUtils;
import java.util.Objects;
public class AdvancedConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "AdvancedConfigsDialog";
String vmId;
DataMainRoms configs;
boolean isSave = true;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorAdvancedDialogBinding binding;
boolean iseditparams;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
// This can happen after the app is freed from memory and then reopened.
if (configs == null) {
isSave = false;
DialogUtils.oopsDialog(requireActivity(), getString(R.string.something_went_wrong));
dismiss();
return EditorUtils.getDummyDialog(requireActivity());
}
binding = CreatorAdvancedDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
public void onResume() {
super.onResume();
if (iseditparams) {
iseditparams = false;
binding.qemu.setText(QemuParamsEditorActivity.result);
}
}
AdvancedConfigsDialogCallback callback;
public void setOnDismiss(AdvancedConfigsDialogCallback callback) {
this.callback = callback;
}
public interface AdvancedConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
if (!isAdded()) return;
binding.qemu.setOnClickListener(v -> {
iseditparams = true;
Intent intent = new Intent();
intent.setClass(requireContext(), QemuParamsEditorActivity.class);
intent.putExtra("content", Objects.requireNonNull(binding.qemu.getText()).toString());
startActivity(intent);
});
binding.qemuField.setOnClickListener(v -> {
iseditparams = true;
Intent intent = new Intent();
intent.setClass(requireContext(), QemuParamsEditorActivity.class);
intent.putExtra("content", Objects.requireNonNull(binding.qemu.getText()).toString());
startActivity(intent);
});
load();
}
private void load() {
if (!isAdded()) return;
binding.qemu.setText(configs.itemExtra);
}
private void save() {
configs.itemExtra = Objects.requireNonNull(binding.qemu.getText()).toString();
}
}

View file

@ -1,134 +0,0 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.R;
import com.vectras.vm.creator.utils.EditorUtils;
import com.vectras.vm.creator.utils.VMCreatorSelector;
import com.vectras.vm.databinding.CreatorBoardDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.utils.DialogUtils;
import java.util.Objects;
public class BoardConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "BoardConfigsDialog";
String vmId;
DataMainRoms configs;
boolean isSave = true;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorBoardDialogBinding binding;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
// This can happen after the app is freed from memory and then reopened.
if (configs == null) {
isSave = false;
DialogUtils.oopsDialog(requireActivity(), getString(R.string.something_went_wrong));
dismiss();
return EditorUtils.getDummyDialog(requireActivity());
}
binding = CreatorBoardDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
BoardConfigsDialogCallback callback;
public void setOnDismiss(BoardConfigsDialogCallback callback) {
this.callback = callback;
}
public interface BoardConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
if (!isAdded()) return;
binding.sbvMachine.setOnClickListener(v -> VMCreatorSelector.machine(requireActivity(), MainSettingsManager.getArch(requireContext()), configs.machine, ((position, name, value) -> {
configs.machine = position;
binding.sbvMachine.setSubtitle(name);
})));
binding.sbvCpu.setOnClickListener(v -> VMCreatorSelector.cpu(requireActivity(), MainSettingsManager.getArch(requireContext()), configs.cpu, ((position, name, value) -> {
configs.cpu = position;
binding.sbvCpu.setSubtitle(name);
})));
binding.sbvCore.setOnClickListener(v -> VMCreatorSelector.cpuCore(requireActivity(), MainSettingsManager.getArch(requireContext()), configs.cores, ((position, name, value) -> {
configs.cores = position;
binding.sbvCore.setSubtitle(name);
})));
binding.sbvThread.setOnClickListener(v -> VMCreatorSelector.cpuThread(requireActivity(), MainSettingsManager.getArch(requireContext()), configs.threads, ((position, name, value) -> {
configs.threads = position;
binding.sbvThread.setSubtitle(name);
})));
if (MainSettingsManager.getArch(requireContext()).equals(MainSettingsManager.PPC_ARCH)) {
binding.cbvNestedVirtualization.setVisibility(View.GONE);
binding.sbvThread.setBackground(AppCompatResources.getDrawable(requireContext(), R.drawable.object_shape_bottom_high));
}
load();
}
private void load() {
if (!isAdded()) return;
binding.sbvMachine.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getMachine(requireContext(), MainSettingsManager.getArch(requireContext()), configs.machine).get("name")).toString());
binding.sbvCpu.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getCpu(requireContext(), MainSettingsManager.getArch(requireContext()), configs.cpu).get("name")).toString());
binding.sbvCore.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getCpuCore(MainSettingsManager.getArch(requireContext()), configs.cores).get("value")).toString());
binding.sbvThread.setSubtitle(String.valueOf(configs.threads + 1));
binding.cbvNestedVirtualization.setChecked(configs.nvirt);
binding.cbvBattery.setChecked(configs.battery);
}
private void save() {
configs.nvirt = binding.cbvNestedVirtualization.isChecked();
configs.battery = binding.cbvBattery.isChecked();
}
}

View file

@ -1,140 +0,0 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.R;
import com.vectras.vm.creator.utils.EditorUtils;
import com.vectras.vm.creator.utils.VMCreatorSelector;
import com.vectras.vm.databinding.CreatorFirmwareDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.utils.DialogUtils;
import java.util.Objects;
public class FirmwareConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "FirmwareConfigsDialog";
String vmId;
DataMainRoms configs;
boolean isSave = true;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorFirmwareDialogBinding binding;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
// This can happen after the app is freed from memory and then reopened.
if (configs == null) {
isSave = false;
DialogUtils.oopsDialog(requireActivity(), getString(R.string.something_went_wrong));
dismiss();
return EditorUtils.getDummyDialog(requireActivity());
}
binding = CreatorFirmwareDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
FirmwareConfigsDialogCallback callback;
public void setOnDismiss(FirmwareConfigsDialogCallback callback) {
this.callback = callback;
}
public interface FirmwareConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
if (!isAdded()) return;
binding.sbvBootfrom.setOnClickListener(v -> VMCreatorSelector.bootFrom(requireActivity(), configs.bootFrom, ((position, name, value) -> {
configs.bootFrom = position;
binding.sbvBootfrom.setSubtitle(name);
})));
binding.cbvShowbootmenu.setOnCheckedChangeListener((v, isChecked) -> configs.isShowBootMenu = isChecked);
binding.cbvUselocaltime.setOnCheckedChangeListener((v, isChecked) -> configs.isUseLocalTime = isChecked);
if (!MainSettingsManager.getArch(requireContext()).equals("X86_64")) {
binding.cbvUseuefi.setVisibility(View.GONE);
binding.cbvUseDefaultBios.setBackground(AppCompatResources.getDrawable(requireContext(), R.drawable.object_shape_single_high));
} else {
binding.cbvUseuefi.setOnCheckedChangeListener((v, isChecked) -> configs.isUseUefi = isChecked);
}
binding.cbvUseDefaultBios.setOnCheckedChangeListener((v, isChecked) -> {
configs.isUseDefaultBios = isChecked;
binding.cbvUseuefi.setEnabled(isChecked);
});
load();
}
private void load() {
if (!isAdded()) return;
binding.sbvBootfrom.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getBootFrom(requireActivity(), configs.bootFrom).get("name")).toString());
binding.cbvShowbootmenu.setChecked(configs.isShowBootMenu);
if (MainSettingsManager.getArch(requireContext()).equals(MainSettingsManager.X86_64_ARCH)) {
binding.cbvUseuefi.setChecked(configs.isUseUefi);
} else {
binding.cbvUseuefi.setVisibility(View.GONE);
}
binding.cbvUseDefaultBios.setChecked(configs.isUseDefaultBios);
binding.cbvUseuefi.setEnabled(configs.isUseDefaultBios);
binding.cbvUselocaltime.setChecked(configs.isUseLocalTime);
}
private void save() {
configs.isShowBootMenu = binding.cbvShowbootmenu.isChecked();
configs.isUseUefi = binding.cbvUseuefi.isChecked();
configs.isUseDefaultBios = binding.cbvUseDefaultBios.isChecked();
configs.isUseLocalTime = binding.cbvUselocaltime.isChecked();
}
}

View file

@ -1,103 +0,0 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.vm.R;
import com.vectras.vm.creator.utils.EditorUtils;
import com.vectras.vm.creator.utils.VMCreatorSelector;
import com.vectras.vm.databinding.CreatorNetworkDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.utils.DialogUtils;
import java.util.Objects;
public class NetworkConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "NetworkConfigsDialog";
String vmId;
DataMainRoms configs;
boolean isSave = true;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorNetworkDialogBinding binding;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
// This can happen after the app is freed from memory and then reopened.
if (configs == null) {
isSave = false;
DialogUtils.oopsDialog(requireActivity(), getString(R.string.something_went_wrong));
dismiss();
return EditorUtils.getDummyDialog(requireActivity());
}
binding = CreatorNetworkDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
NetworkConfigsDialogCallback callback;
public void setOnDismiss(NetworkConfigsDialogCallback callback) {
this.callback = callback;
}
public interface NetworkConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
if (!isAdded()) return;
binding.sbvCardType.setOnClickListener(v -> VMCreatorSelector.networkCard(requireActivity(), configs.networkCard, ((position, name, value) -> {
configs.networkCard = position;
binding.sbvCardType.setSubtitle(name);
})));
load();
}
private void load() {
if (!isAdded()) return;
binding.sbvCardType.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getNetworkCard(requireActivity(), configs.networkCard).get("name")).toString());
}
private void save() {
// It may be used in subsequent versions.
}
}

View file

@ -1,609 +0,0 @@
package com.vectras.vm.creator.editor;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.AppConfig;
import com.vectras.vm.Fragment.CreateImageDialogFragment;
import com.vectras.vm.R;
import com.vectras.vm.creator.utils.CreatorUtils;
import com.vectras.vm.creator.utils.EditorUtils;
import com.vectras.vm.databinding.CreatorStorageDialogBinding;
import com.vectras.vm.file.FilePickerDialog;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.manager.FormatManager;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.IntentUtils;
import com.vectras.vm.utils.ProgressDialog;
import java.io.File;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class StorageConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "StorageConfigsDialog";
String vmId;
DataMainRoms configs;
boolean isSave = true;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
if (isAdded()) utils = new CreatorUtils(requireActivity(), vmId);
}
}
CreatorStorageDialogBinding binding;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private CreatorUtils utils;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
// This can happen after the app is freed from memory and then reopened.
if (configs == null) {
isSave = false;
DialogUtils.oopsDialog(requireActivity(), getString(R.string.something_went_wrong));
dismiss();
return EditorUtils.getDummyDialog(requireActivity());
}
binding = CreatorStorageDialogBinding.inflate(getLayoutInflater());
utils = new CreatorUtils(requireActivity(), vmId);
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
StorageConfigsDialogCallback callback;
public void setOnDismiss(StorageConfigsDialogCallback callback) {
this.callback = callback;
}
public interface StorageConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
private final ActivityResultLauncher<String> diskPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
handleDiskFile(uri);
});
@SuppressLint("SetTextI18n")
private final ActivityResultLauncher<String> isoPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
String fileName = FileUtils.getFileNameFromUri(requireActivity(), uri);
if (fileName != null && !fileName.isEmpty() && !FormatManager.isOpticalFileFormat(fileName)) {
DialogUtils.twoDialog(requireActivity(), getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported_optical_drive), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.album_24px, true,
() -> handleFile(uri), null, null);
} else {
handleFile(uri);
}
});
@SuppressLint("SetTextI18n")
private final ActivityResultLauncher<String> floppyPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri == null) return;
String fileName = FileUtils.getFileNameFromUri(requireActivity(), uri);
if (fileName != null && !fileName.isEmpty() && !FormatManager.isFloppyFileFormat(fileName)) {
DialogUtils.twoDialog(requireActivity(), getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported_floppy_drive), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.save_24px, true,
() -> handleFile(uri), null, null);
} else {
handleFile(uri);
}
});
private void handleFile(Uri uri) {
if (!isAdded()) return;
if (MainSettingsManager.copyFile(requireActivity())) {
utils.showProgressDialog(getString(R.string.copying_file));
executor.execute(() -> {
try {
String path = utils.copyToTemp(uri);
if (isAdded())
requireActivity().runOnUiThread(() -> setDrive(PENDING_SELECT_FILE_MODE, path));
} catch (Exception e) {
if (isAdded())
requireActivity().runOnUiThread(() -> DialogUtils.oneDialog(requireActivity(),
getString(R.string.oops),
getString(R.string.unable_to_copy_file_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null));
Log.e(TAG, "isoPicker: " + e.getMessage());
} finally {
if (isAdded())
requireActivity().runOnUiThread(() -> utils.dissmissProgressDialog());
}
});
} else {
executor.execute(() -> {
CreatorUtils.FilePathData filePathData = utils.getFilePath(uri);
if (!isAdded()) return;
if (!filePathData.isValid) {
requireActivity().runOnUiThread(() -> DialogUtils.oneDialog(requireActivity(),
getString(R.string.problem_has_been_detected),
getString(R.string.invalid_file_path_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null)
);
} else {
requireActivity().runOnUiThread(() -> utils.showProgressDialog(getString(R.string.just_a_moment)));
requireActivity().runOnUiThread(() -> {
setDrive(PENDING_SELECT_FILE_MODE, new File(filePathData.path).getAbsolutePath());
utils.dissmissProgressDialog();
});
}
});
}
}
private void handleDiskFile(Uri uri) {
if (!isAdded()) return;
utils.showProgressDialog(getString(R.string.just_a_moment));
new Thread(() -> {
CreatorUtils.FilePathData filePathData = utils.getFilePath(uri);
if (!isAdded()) return;
if (filePathData.isValid) {
requireActivity().runOnUiThread(() -> {
utils.dissmissProgressDialog();
if (FormatManager.isHardDriveFileFormat(filePathData.name)) {
startHandleHardDriveFile(uri);
} else {
DialogUtils.twoDialog(requireActivity(), getString(R.string.problem_has_been_detected), getString(R.string.file_format_is_not_supported_hard_drive), getResources().getString(R.string.continuetext), getResources().getString(R.string.cancel), true, R.drawable.hard_drive_24px, true,
() -> startHandleHardDriveFile(uri), null, null);
}
});
} else {
requireActivity().runOnUiThread(() -> startHandleHardDriveFile(uri));
}
}).start();
}
@SuppressLint("SetTextI18n")
private void startHandleHardDriveFile(Uri _content_describer) {
if (!isAdded()) return;
if (MainSettingsManager.copyFile(requireActivity())) {
if (requireActivity().isFinishing() || requireActivity().isDestroyed()) return;
utils.showProgressDialog(getString(R.string.copying_file));
executor.execute(() -> {
try {
if (!isAdded()) return;
String _filename = FileUtils.getFileNameFromUri(requireActivity(), _content_describer);
if (_filename == null || _filename.isEmpty()) {
_filename = String.valueOf(System.currentTimeMillis());
}
String path = utils.copyToTemp(_content_describer);
String final_filename = _filename;
if (!isAdded()) return;
requireActivity().runOnUiThread(() -> {
if (requireActivity().isFinishing() || requireActivity().isDestroyed()) {
if (!vmId.isEmpty())
FileUtils.delete(new File(VmFileManager.getPath(vmId, final_filename)));
return;
}
setDrive(PENDING_SELECT_FILE_MODE, path);
});
} catch (Exception e) {
if (!isAdded()) requireActivity().runOnUiThread(() -> DialogUtils.oneDialog(requireActivity(),
getString(R.string.oops),
getString(R.string.unable_to_copy_hard_drive_file_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null));
} finally {
if (!isAdded()) requireActivity().runOnUiThread(() -> utils.dissmissProgressDialog());
}
});
} else {
utils.showProgressDialog(getString(R.string.just_a_moment));
new Thread(() -> {
String path = FileUtils.getPath(requireContext(), _content_describer);
if (!isAdded()) return;
requireActivity().runOnUiThread(() -> {
utils.dissmissProgressDialog();
if (!FileUtils.isValidFilePath(requireActivity(), path, false)) {
DialogUtils.oneDialog(requireActivity(),
getString(R.string.problem_has_been_detected),
getString(R.string.invalid_file_path_content),
getString(R.string.ok),
true,
R.drawable.warning_48px,
true,
null,
null);
} else {
setDrive(PENDING_SELECT_FILE_MODE, path);
}
});
}).start();
}
}
private void onFileChange(String fileName) {
utils.markDelete(VmFileManager.getPath(vmId, fileName));
}
// STORAGE LOGIC CORE
private void initialize() {
if (!isAdded()) return;
binding.drive.setOnClickListener(v -> pickStorageFile(SELECT_DISK_0_FILE_MODE));
binding.driveField.setOnClickListener(v -> pickStorageFile(SELECT_DISK_0_FILE_MODE));
binding.driveField.setEndIconOnClickListener(v -> {
if (Objects.requireNonNull(binding.drive.getText()).toString().isEmpty()) {
callQcow2CreatorDialog(SELECT_DISK_0_FILE_MODE);
} else {
storageFileOptionDialog(SELECT_DISK_0_FILE_MODE);
}
});
binding.tieHd1.setOnClickListener(v -> pickStorageFile(SELECT_DISK_1_FILE_MODE));
binding.tilHd1.setOnClickListener(v -> pickStorageFile(SELECT_DISK_1_FILE_MODE));
binding.tilHd1.setEndIconOnClickListener(v -> {
if (Objects.requireNonNull(binding.tieHd1.getText()).toString().isEmpty()) {
callQcow2CreatorDialog(SELECT_DISK_1_FILE_MODE);
} else {
storageFileOptionDialog(SELECT_DISK_1_FILE_MODE);
}
});
if (MainSettingsManager.getArch(requireActivity()).equals(MainSettingsManager.ARM64_ARCH)) {
binding.lnFloppyContainer.setVisibility(View.GONE);
}
binding.tieFda.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_A_FILE_MODE));
binding.tilFda.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_A_FILE_MODE));
binding.tilFda.setEndIconOnClickListener(v -> setDrive(SELECT_FLOPPY_A_FILE_MODE, null));
binding.tieFdb.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_B_FILE_MODE));
binding.tilFdb.setOnClickListener(v -> pickStorageFile(SELECT_FLOPPY_B_FILE_MODE));
binding.tilFdb.setEndIconOnClickListener(v -> setDrive(SELECT_FLOPPY_B_FILE_MODE, null));
binding.cdrom.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_0_FILE_MODE));
binding.cdromField.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_0_FILE_MODE));
binding.cdromField.setEndIconOnClickListener(v -> setDrive(SELECT_CDROM_0_FILE_MODE, null));
binding.tieCdrom1.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_1_FILE_MODE));
binding.tilCdrom1.setOnClickListener(v -> pickStorageFile(SELECT_CDROM_1_FILE_MODE));
binding.tilCdrom1.setEndIconOnClickListener(v -> setDrive(SELECT_CDROM_1_FILE_MODE, null));
binding.svSharedFolder.setSubTitle(AppConfig.sharedFolder);
load();
}
private final int SELECT_DISK_0_FILE_MODE = 0;
private final int SELECT_DISK_1_FILE_MODE = 1;
public final int SELECT_CDROM_0_FILE_MODE = 2;
public final int SELECT_CDROM_1_FILE_MODE = 3;
public final int SELECT_FLOPPY_A_FILE_MODE = 4;
public final int SELECT_FLOPPY_B_FILE_MODE = 5;
private int PENDING_SELECT_FILE_MODE = 0;
private String PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = "";
private void pickStorageFile(int mode) {
if (!isAdded()) return;
PENDING_SELECT_FILE_MODE = mode;
PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = Objects.requireNonNull(getPeddingStorageEditText().getText()).toString();
try {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE) {
if (MainSettingsManager.getBuiltInFilePicker(requireActivity())) {
builtInFilePicker(PICK_OPTICAL_FILE_MODE);
} else {
isoPicker.launch("*/*");
}
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
if (MainSettingsManager.getBuiltInFilePicker(requireActivity())) {
builtInFilePicker(PICK_FLOPPY_FILE_MODE);
} else {
floppyPicker.launch("*/*");
}
} else {
if (MainSettingsManager.getBuiltInFilePicker(requireActivity())) {
builtInFilePicker(PICK_DRIVE_FILE_MODE);
} else {
diskPicker.launch("*/*");
}
}
} catch (Exception e) {
Log.e(TAG, "pickStorageFile: ", e);
IntentUtils.showErrorDialog(requireActivity());
}
}
private void storageFileOptionDialog(int mode) {
if (!isAdded()) return;
PENDING_SELECT_FILE_MODE = mode;
//TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
TextInputEditText peddingTextInputEditText = getPeddingStorageEditText();
DialogUtils.threeDialog(requireActivity(),
getString(R.string.change_hard_drive),
getString(R.string.do_you_want_to_change_create_or_remove),
getString(R.string.change), getString(R.string.remove),
getString(R.string.create),
true,
R.drawable.hard_drive_24px,
true,
() -> pickStorageFile(mode),
() -> {
String path = new File(Objects.requireNonNull(peddingTextInputEditText.getText()).toString()).getAbsolutePath();
if (path.startsWith(VmFileManager.quickGetPath(vmId))) {
ProgressDialog progressDialog1 = new ProgressDialog(requireActivity());
progressDialog1.show();
new Thread(() -> {
utils.markDelete(path);
requireActivity().runOnUiThread(progressDialog1::reset);
}).start();
}
setDrive(mode, "");
},
() -> callQcow2CreatorDialog(PENDING_SELECT_FILE_MODE), null);
}
private void callQcow2CreatorDialog(int mode) {
PENDING_SELECT_FILE_MODE = mode;
TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
TextInputEditText peddingTextInputEditText = getPeddingStorageEditText();
CreateImageDialogFragment dialogFragment = new CreateImageDialogFragment();
dialogFragment.folder = VmFileManager.getPath(vmId);
dialogFragment.customRom = true;
dialogFragment.filename = configs.itemName;
dialogFragment.drive = peddingTextInputEditText;
dialogFragment.driveLayout = peddingTextInputLayout;
dialogFragment.isMarkPendingAdd = true;
dialogFragment.show(requireActivity().getSupportFragmentManager(), "CreateImageDialogFragment");
}
private void setRemovableDriveEndIconOnClickListener(int mode, TextInputLayout textInputLayout) {
textInputLayout.setEndIconOnClickListener(v -> {
PENDING_SELECT_FILE_MODE = mode;
PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = Objects.requireNonNull(getPeddingStorageEditText().getText()).toString();
setDrive(mode, null);
});
}
private void setDrive(Integer mode, String path) {
if (!isAdded()) return;
if (isFileReadyinUse(path)) {
DialogUtils.oopsDialog(requireActivity(), getString(R.string.vm_creator_this_file_is_already_in_use_content));
utils.deleteTemp(new File(path).getName());
return;
}
if (mode != null) PENDING_SELECT_FILE_MODE = mode;
TextInputLayout peddingTextInputLayout = getPeddingStorageInputLayout();
TextInputEditText peddingTextInputEditText = getPeddingStorageEditText();
peddingTextInputEditText.setText(path != null ? path : "");
if (path == null || path.isEmpty()) {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
peddingTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_NONE);
} else {
peddingTextInputLayout.setEndIconDrawable(R.drawable.add_24px);
}
} else {
if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE || PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
peddingTextInputLayout.setEndIconMode(TextInputLayout.END_ICON_CUSTOM);
peddingTextInputLayout.setEndIconDrawable(R.drawable.close_24px);
setRemovableDriveEndIconOnClickListener(PENDING_SELECT_FILE_MODE, peddingTextInputLayout);
} else {
peddingTextInputLayout.setEndIconDrawable(R.drawable.more_vert_24px);
}
}
if (!PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE.isEmpty()) {
onFileChange(new File(PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE).getName());
PENDING_OLD_FILE_AFTER_SELECTED_NEW_FILE = "";
}
}
private TextInputLayout getPeddingStorageInputLayout() {
if (PENDING_SELECT_FILE_MODE == SELECT_DISK_1_FILE_MODE) {
return binding.tilHd1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE) {
return binding.cdromField;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE) {
return binding.tilCdrom1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
return binding.tilFda;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
return binding.tilFdb;
} else {
return binding.driveField;
}
}
private TextInputEditText getPeddingStorageEditText() {
if (PENDING_SELECT_FILE_MODE == SELECT_DISK_1_FILE_MODE) {
return binding.tieHd1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_0_FILE_MODE) {
return binding.cdrom;
} else if (PENDING_SELECT_FILE_MODE == SELECT_CDROM_1_FILE_MODE) {
return binding.tieCdrom1;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_A_FILE_MODE) {
return binding.tieFda;
} else if (PENDING_SELECT_FILE_MODE == SELECT_FLOPPY_B_FILE_MODE) {
return binding.tieFdb;
} else {
return binding.drive;
}
}
private boolean isFileReadyinUse(String path) {
if (path == null || path.trim().isEmpty()) return false;
String paramCollection = Objects.requireNonNull(binding.drive.getText()).toString();
paramCollection += "\n" + Objects.requireNonNull(binding.tieHd1.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.cdrom.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieCdrom1.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieFda.getText());
paramCollection += "\n" + Objects.requireNonNull(binding.tieFdb.getText());
paramCollection += "\n" + Objects.requireNonNull(configs.itemExtra);
return paramCollection.contains(path);
}
final int PICK_DRIVE_FILE_MODE = 0;
final int PICK_OPTICAL_FILE_MODE = 1;
final int PICK_FLOPPY_FILE_MODE = 2;
private void builtInFilePicker(int mode) {
if (!isAdded()) return;
FilePickerDialog filePickerDialog = new FilePickerDialog();
int finalMode;
if (mode == PICK_DRIVE_FILE_MODE) {
finalMode = FilePickerDialog.FIT_PICK_DISK_FILE_MODE;
} else if (mode == PICK_OPTICAL_FILE_MODE) {
finalMode = FilePickerDialog.FIT_PICK_OPTICAL_FILE_MODE;
} else {
finalMode = FilePickerDialog.FIT_PICK_FLOPPY_FILE_MODE;
}
filePickerDialog.pick(requireActivity(), finalMode, (path -> handleFile(Uri.fromFile(new File(path)))));
}
private void load() {
if (configs.itemPath != null && !configs.itemPath.isEmpty()) {
setDrive(SELECT_DISK_0_FILE_MODE, (configs.itemPath.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.itemPath));
}
if (configs.hd1 != null && !configs.hd1.isEmpty()) {
setDrive(SELECT_DISK_1_FILE_MODE, (configs.hd1.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.hd1));
}
if (MainSettingsManager.getArch(getContext()).equals(MainSettingsManager.ARM64_ARCH)) {
binding.lnFloppyContainer.setVisibility(View.GONE);
} else {
if (configs.fda != null && !configs.fda.isEmpty()) {
setDrive(SELECT_FLOPPY_A_FILE_MODE, (configs.fda.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.fda));
}
if (configs.fdb != null && !configs.fdb.isEmpty()) {
setDrive(SELECT_FLOPPY_B_FILE_MODE, (configs.fdb.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.fdb));
}
}
if (configs.imgCdrom != null && !configs.imgCdrom.isEmpty()) {
setDrive(SELECT_CDROM_0_FILE_MODE, (configs.imgCdrom.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.imgCdrom));
}
if (configs.cdrom1 != null && !configs.cdrom1.isEmpty()) {
setDrive(SELECT_CDROM_1_FILE_MODE, (configs.cdrom1.contains("/") ? "" : VmFileManager.getPath(vmId)).concat(configs.cdrom1));
}
binding.svSharedFolder.setChecked(configs.sharedFolder);
}
private void save() {
configs.itemPath = Objects.requireNonNull(binding.drive.getText()).toString();
configs.hd1 = Objects.requireNonNull(binding.tieHd1.getText()).toString();
configs.fda = Objects.requireNonNull(binding.tieFda.getText()).toString();
configs.fdb = Objects.requireNonNull(binding.tieFdb.getText()).toString();
configs.imgCdrom = Objects.requireNonNull(binding.cdrom.getText()).toString();
configs.cdrom1 = Objects.requireNonNull(binding.tieCdrom1.getText()).toString();
configs.sharedFolder = binding.svSharedFolder.isChecked();
}
}

View file

@ -1,107 +0,0 @@
package com.vectras.vm.creator.utils;
import android.app.Activity;
import android.net.Uri;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.ProgressDialog;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class CreatorUtils {
public static final String PENDING_FOLDER = "pending/";
Activity activity;
String vmId;
ProgressDialog progressDialog;
public CreatorUtils(Activity activity, String vmId) {
this.activity = activity;
this.vmId = vmId;
}
public void showProgressDialog(String message) {
if (progressDialog == null) progressDialog = new ProgressDialog(activity);
progressDialog.setText(message);
if (!activity.isFinishing() && !activity.isDestroyed()) progressDialog.show();
}
public void dissmissProgressDialog() {
if (progressDialog != null && !activity.isFinishing() && !activity.isDestroyed()) {
progressDialog.dismiss();
}
}
public String getTempPath(String fileName) {
return VmFileManager.getTempPath(activity, vmId, PENDING_FOLDER + fileName);
}
public boolean removeTemp() {
return VmFileManager.removeTemp(activity, vmId, PENDING_FOLDER);
}
public String copyToTemp(Uri uri) throws IOException {
String fileName = FileUtils.getFileNameFromUri(activity, uri);
if (fileName == null || fileName.isEmpty()) {
fileName = String.valueOf(System.currentTimeMillis());
}
FileUtils.copyFileFromUri(activity, uri, VmFileManager.getTempPath(activity, vmId, PENDING_FOLDER + fileName));
return VmFileManager.getPath(vmId, fileName);
}
public void moveAllFromTemp() {
ArrayList<String> fileList = new ArrayList<>();
FileUtils.getAListOfAllFilesAndFoldersInADirectory(VmFileManager.getTempPath(activity, vmId, PENDING_FOLDER), fileList);
for (int position = 0; position < fileList.size(); position++) {
FileUtils.moveToFolder(fileList.get(position), VmFileManager.getPath(vmId));
}
ArrayList<String> fileListInternal = new ArrayList<>();
FileUtils.getAListOfAllFilesAndFoldersInADirectory(VmFileManager.getInternalTempPath(activity, vmId, PENDING_FOLDER), fileListInternal);
for (int position = 0; position < fileListInternal.size(); position++) {
FileUtils.moveToFolder(fileListInternal.get(position), VmFileManager.getPath(vmId));
}
}
public void deleteTemp(String fileName) {
VmFileManager.removeTemp(activity, vmId, PENDING_FOLDER + fileName);
}
public void markDelete(String path) {
VmFileManager.markPendingDelete(path);
deleteTemp(new File(path).getName());
}
public FilePathData getFilePath(Uri uri) {
try {
String filePath = FileUtils.getPath(activity, uri);
if (filePath != null && FileUtils.isFileExists(filePath)) {
return new FilePathData() {
{
isValid = true;
path = filePath;
name = new File(filePath).getName();
}
};
}
} catch (Exception e) {
return new FilePathData();
}
return new FilePathData();
}
public static class FilePathData {
public boolean isValid = false;
public String path;
public String name;
}
}

View file

@ -1,20 +0,0 @@
package com.vectras.vm.creator.utils;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.WindowManager;
import com.google.android.material.bottomsheet.BottomSheetDialog;
public class EditorUtils {
public static BottomSheetDialog getDummyDialog(Activity activity) {
BottomSheetDialog dialog = new BottomSheetDialog(activity);
if (dialog.getWindow() != null) {
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
return dialog;
}
}

View file

@ -3,14 +3,11 @@ package com.vectras.vm.fcm;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessaging;
import com.vectras.vm.AppConfig;
public class FCMManager {
private static final String TAG = "FCMManager";
public static void subscribe() {
if (!AppConfig.isGmsAvailable) return;
FirebaseMessaging.getInstance()
.subscribeToTopic("vectrasvmandroidgithub")
.addOnCompleteListener(task -> {
@ -23,8 +20,6 @@ public class FCMManager {
}
public static void unSubscribe() {
if (!AppConfig.isGmsAvailable) return;
FirebaseMessaging.getInstance()
.unsubscribeFromTopic("vectrasvmandroidgithub")
.addOnCompleteListener(task -> {

View file

@ -1,9 +0,0 @@
package com.vectras.vm.file;
public class FilePickerData {
String name = "";
String path = "";
int type = -1;
int icon = -1;
boolean enabled = true;
}

View file

@ -1,469 +0,0 @@
package com.vectras.vm.file;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.vectras.vm.R;
import com.vectras.vm.databinding.DialogFilePickerBinding;
import com.vectras.vm.databinding.ListFileBinding;
import com.vectras.vm.manager.FormatManager;
import com.vectras.vm.utils.ClipboardUltils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.IntentUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
public class FilePickerDialog extends DialogFragment {
DialogFilePickerBinding binding;
LinearLayoutManager layoutmanager;
RecyclerviewAdapter adapter;
FilePickerDialogCallback callback;
FilePickerSettings settings;
String currentPath = "";
String homeName;
String homePath;
boolean lockHome;
int pickType = -1;
boolean isShowHiddenFile;
boolean isShowHiddenDiviers;
boolean fixTextColor;
int textColor;
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
binding = DialogFilePickerBinding.inflate(getLayoutInflater());
settings = new FilePickerSettings(requireActivity());
isShowHiddenFile = settings.showHiddenFiles();
isShowHiddenDiviers = settings.divider();
if (fixTextColor) {
textColor = binding.tvTitle.getCurrentTextColor();
binding.tvFullPath.setTextColor(textColor);
binding.tvNothingHere.setTextColor(textColor);
}
AlertDialog dialog = new AlertDialog.Builder(requireActivity()).create();
dialog.setView(binding.getRoot());
layoutmanager = new LinearLayoutManager(requireActivity());
adapter = new RecyclerviewAdapter(requireActivity(), dialog, new ArrayList<>(), callback);
binding.list.setAdapter(adapter);
binding.list.setLayoutManager(layoutmanager);
binding.list.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView rv, int dx, int dy) {
boolean canScrollUp = rv.canScrollVertically(-1);
boolean canScrollDown = rv.canScrollVertically(1);
binding.dvTop.setVisibility(canScrollUp ? View.VISIBLE : View.INVISIBLE);
binding.dvBottom.setVisibility(canScrollDown ? View.VISIBLE : View.INVISIBLE);
}
});
String lastPath = new File(settings.lastPath()).exists() ? settings.lastPath() : Environment.getExternalStorageDirectory().getAbsolutePath();
adapter.load((homePath != null && new File(homePath).exists()) ? homePath : lastPath);
binding.btnHome.setOnClickListener(v -> adapter.load(homePath != null && new File(homePath).exists() ? homePath : Environment.getExternalStorageDirectory().getAbsolutePath()));
binding.btnUp.setOnClickListener(v -> adapter.load(new File(currentPath).getParent()));
if (pickType == BROWSE_MODE) {
binding.btnOpenInOtherApp.setOnClickListener(v -> {
if (!isAdded()) return;
FileUtils.openFolder(requireContext(), currentPath);
dismiss();
});
} else {
binding.btnOpenInOtherApp.setVisibility(View.GONE);
}
binding.tvFullPath.setOnClickListener(v -> {
if (!isAdded()) return;
ClipboardUltils.copyToClipboard(requireContext(), currentPath, false);
Toast.makeText(requireContext(), R.string.the_folder_path_has_been_copied_to_the_clipboard, Toast.LENGTH_SHORT).show();
});
binding.btnClose.setOnClickListener(v -> dismiss());
return dialog;
}
public void setFixTextColor(boolean isEnable) {
fixTextColor = isEnable;
}
public void setHomeName(String name) {
homeName = name;
}
public void setHomePath(String path) {
homePath = new File(path).getAbsolutePath();
}
public void setLockHome(boolean lock) {
lockHome = lock;
}
public void browse(Activity activity) {
pickType = BROWSE_MODE;
show(((FragmentActivity) activity).getSupportFragmentManager(), "file_picker");
}
public void browse(Activity activity, String path) {
setHomePath(path);
browse(activity);
}
public void pick(Activity activity, int type, FilePickerDialogCallback callback) {
this.callback = callback;
pickType = type;
show(((FragmentActivity) activity).getSupportFragmentManager(), "file_picker");
}
public void updateUpButton(String path) {
if (path.equals(Environment.getExternalStorageDirectory().getAbsolutePath())) {
binding.tvTitle.setText(R.string.internal_storage);
binding.btnHome.setVisibility(View.GONE);
binding.btnUp.setVisibility(View.INVISIBLE);
binding.btnUp.setEnabled(false);
} else if (lockHome && homePath.equals(path)) {
binding.tvTitle.setText(homeName.isEmpty() ? new File(path).getName() : homeName);
binding.btnHome.setVisibility(View.GONE);
binding.btnUp.setVisibility(View.INVISIBLE);
binding.btnUp.setEnabled(false);
} else {
binding.tvTitle.setText(new File(path).getName());
binding.btnHome.setVisibility(View.VISIBLE);
binding.btnUp.setVisibility(View.VISIBLE);
binding.btnUp.setEnabled(true);
}
binding.tvFullPath.setText(path);
}
boolean isLoading;
private ArrayList<FilePickerData> loadFileList(String path) {
currentPath = path;
new Handler(Looper.getMainLooper()).post(() -> updateUpButton(path));
ArrayList<FilePickerData> list = new ArrayList<>();
File dir = new File(path);
if (!dir.exists() || dir.isFile()) return list;
File[] listFiles = dir.listFiles();
if (listFiles == null || listFiles.length == 0) return list;
list.clear();
for (File file : listFiles) {
if (!isShowHiddenFile && file.getName().startsWith(".")) continue;
FilePickerData item = new FilePickerData();
item.name = file.getName();
item.path = file.getAbsolutePath();
item.type = file.isDirectory() ? TYPE_FOLDER : getType(file.getName());
item.icon = getIcon(item.type);
item.enabled = pickType == TYPE_FILE || pickType == BROWSE_MODE || item.type == TYPE_FOLDER || (pickType >= FIT_PICK_DISK_FILE_MODE ? checkFitPickFileMode(item.name) : item.type == pickType);
list.add(item);
}
Collections.sort(list, (o1, o2) -> {
if (o1.name == null || o2.name == null) {
return 0;
}
return o1.name.compareToIgnoreCase(o2.name);
});
return list;
}
public static final int BROWSE_MODE = -1;
public static final int TYPE_FILE = 0;
public static final int TYPE_FOLDER = 1;
public static final int AUDIO_FILE = 2;
public static final int VIDEO_FILE = 3;
public static final int IMAGE_FILE = 4;
public static final int DOCUMENT_FILE = 5;
public static final int APPLICATION_FILE = 6;
public static final int DISK_FILE = 7;
public static final int ISO_FILE = 8;
public static final int FLOPPY_FILE = 9;
public static final int ROM_FILE = 10;
public static final int SHELL_FILE = 11;
public static final int DB_FILE = 12;
public static final int LOG_FILE = 13;
public static final int WINDOWS_FILE = 14;
public static final int CONFIG_FILE = 15;
public static final int ZIP_FILE = 16;
public static final int DEV_FILE = 17;
public static final int SYSTEM_FILE = 18;
public static final int PACKAGE_FILE = 19;
public static final int FONT_FILE = 20;
public static final int KEY_FILE = 21;
public static final int IOS_FILE = 22;
private int getType(String fileName) {
if (!fileName.contains(".")) return TYPE_FILE;
String extension = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
return switch (extension) {
case ".mp3", ".wav", ".ogg", ".flac", ".m4a", ".aif", ".wma", ".smi" -> AUDIO_FILE;
case ".mp4", ".webm", ".mov", ".mkv", ".avi", ".wmv" -> VIDEO_FILE;
case ".jpg", ".jpeg", ".png", ".gif", ".webp", ".raw" -> IMAGE_FILE;
case ".pdf", ".txt", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".md", ".csv" -> DOCUMENT_FILE;
case ".apk", ".xapk", ".apkm", ".apks" -> APPLICATION_FILE;
case ".img", ".qcow2", ".vhd", ".vhdx", ".vdi", ".qcow", ".vmdk", ".vpc" -> DISK_FILE;
case ".iso", ".cdr", ".toast" -> ISO_FILE;
case ".flp", ".ima" -> FLOPPY_FILE;
case ".cvbi" -> ROM_FILE;
case ".sh", ".cmd", ".bat", ".ps1" -> SHELL_FILE;
case ".json", ".db", ".sqlite", ".sqlite3", ".dbf", ".accdb", ".mdf", ".ldf", ".ibd", ".frm", ".parquet", ".orc", ".kdbx" -> DB_FILE;
case ".log" -> LOG_FILE;
case ".exe", ".msi", ".msix", ".appx", ".msixbundle" -> WINDOWS_FILE;
case ".conf", ".ini" -> CONFIG_FILE;
case ".zip", ".7z", ".rar" -> ZIP_FILE;
case ".java", ".kt", ".js", ".py", ".c", ".cpp", ".h", ".xml", ".html", ".css", ".lua", ".go", ".asl" -> DEV_FILE;
case ".dll" -> SYSTEM_FILE;
case ".deb", ".rpm" -> PACKAGE_FILE;
case ".ttf", ".otf" -> FONT_FILE;
case ".jks" -> KEY_FILE;
case ".ipa", ".ipsw" -> IOS_FILE;
default -> TYPE_FILE;
};
}
private int getIcon(int type) {
return switch (type) {
case TYPE_FOLDER -> R.drawable.folder_24px;
case AUDIO_FILE -> R.drawable.music_note_24px;
case VIDEO_FILE -> R.drawable.movie_24px;
case IMAGE_FILE -> R.drawable.image_24px;
case DOCUMENT_FILE -> R.drawable.description_24px;
case APPLICATION_FILE -> R.drawable.android_24px;
case DISK_FILE -> R.drawable.hard_drive_24px;
case ISO_FILE -> R.drawable.album_24px;
case ROM_FILE -> R.drawable.vectras_vm_24px;
case SHELL_FILE -> R.drawable.terminal_24px;
case DB_FILE -> R.drawable.database_24px;
case LOG_FILE -> R.drawable.monitor_heart_24px;
case WINDOWS_FILE -> R.drawable.wysiwyg_24px;
case CONFIG_FILE -> R.drawable.tune_24px;
case ZIP_FILE -> R.drawable.folder_zip_24px;
case DEV_FILE -> R.drawable.code_24px;
case SYSTEM_FILE -> R.drawable.settings_24px;
case PACKAGE_FILE -> R.drawable.package_24px;
case FONT_FILE -> R.drawable.titlecase_24px;
case KEY_FILE -> R.drawable.key_24px;
case IOS_FILE -> R.drawable.ios_24px;
default -> R.drawable.draft_24px;
};
}
public static final int FIT_PICK_DISK_FILE_MODE = 20;
public static final int FIT_PICK_OPTICAL_FILE_MODE = 21;
public static final int FIT_PICK_FLOPPY_FILE_MODE = 22;
public boolean checkFitPickFileMode(String fileName) {
if (pickType == FIT_PICK_DISK_FILE_MODE) {
return FormatManager.isHardDriveFileFormat(fileName);
} else if (pickType == FIT_PICK_OPTICAL_FILE_MODE) {
return FormatManager.isOpticalFileFormat(fileName);
} else if (pickType == FIT_PICK_FLOPPY_FILE_MODE) {
return FormatManager.isFloppyFileFormat(fileName);
} else {
return false;
}
}
public interface FilePickerDialogCallback {
void onPicked(String path);
}
private class RecyclerviewAdapter extends RecyclerView.Adapter<RecyclerviewAdapter.ViewHolder> {
Activity activity;
ArrayList<FilePickerData> data;
AlertDialog dialog;
FilePickerDialogCallback callback;
public RecyclerviewAdapter(Activity activity, AlertDialog alertDialog, ArrayList<FilePickerData> arr, FilePickerDialogCallback callback) {
this.activity = activity;
data = arr;
dialog = alertDialog;
this.callback = callback;
}
@NonNull
@Override
public RecyclerviewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = activity.getLayoutInflater();
ListFileBinding binding1 = ListFileBinding.inflate(inflater, parent, false);
return new RecyclerviewAdapter.ViewHolder(binding1.getRoot());
}
@Override
public void onBindViewHolder(RecyclerviewAdapter.ViewHolder holder, final int position) {
View view = holder.itemView;
TextView text = view.findViewById(R.id.text);
ImageView icon = view.findViewById(R.id.icon);
text.setText(data.get(position).name);
icon.setImageResource(data.get(position).icon);
if (fixTextColor) text.setTextColor(textColor);
LinearLayout main = view.findViewById(R.id.main);
if (data.get(position).enabled) {
main.setEnabled(true);
main.setAlpha(1f);
main.setOnClickListener(v -> {
if (data.get(position).type == TYPE_FOLDER) {
load(data.get(position).path);
} else {
if (activity.isFinishing() || activity.isDestroyed()) return;
if (pickType == BROWSE_MODE) {
openFile(data.get(position).path);
} else {
if (callback != null) callback.onPicked(data.get(position).path);
settings.lastPath(currentPath);
dialog.dismiss();
}
}
});
} else {
main.setAlpha(0.5f);
main.setOnClickListener(null);
main.setEnabled(false);
}
if (!isShowHiddenDiviers || position == data.size() - 1) {
view.findViewById(R.id.md_inset_bottom).setVisibility(View.GONE);
} else {
view.findViewById(R.id.md_inset_bottom).setVisibility(View.VISIBLE);
}
}
@Override
public int getItemCount() {
return data.size();
}
public void load(String path) {
isLoading = true;
new Handler(Looper.getMainLooper()).postDelayed(() -> {
if (isAdded() && isLoading) binding.lnLoading.setVisibility(View.VISIBLE);
}, 200);
new Thread(() -> {
ArrayList<FilePickerData> data1 = loadFileList(path);
new Handler(Looper.getMainLooper()).post(() -> {
if (!isAdded()) return;
if (data1.isEmpty()) {
binding.lnEmpty.setVisibility(View.VISIBLE);
binding.lnBrowse.setVisibility(View.INVISIBLE);
} else {
binding.lnEmpty.setVisibility(View.INVISIBLE);
binding.lnBrowse.setVisibility(View.VISIBLE);
data.clear();
data.addAll(data1);
notifyDataSetChanged();
}
binding.lnLoading.setVisibility(View.GONE);
isLoading = false;
});
}).start();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View v) {
super(v);
}
}
}
public void openFile(String path) {
File file = new File(path);
if (!file.exists()) {
if (!isAdded()) return;
IntentUtils.showErrorDialog(requireActivity());
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri fileUri;
if (!isAdded()) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
String authority = requireActivity().getPackageName() + ".provider";
fileUri = FileProvider.getUriForFile(requireContext(), authority, file);
} else {
fileUri = Uri.fromFile(file);
}
String extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
if (mimeType == null) {
mimeType = "*/*";
}
intent.setDataAndType(fileUri, mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent chooserIntent = Intent.createChooser(intent, getString(R.string.open_with));
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (!isAdded()) return;
if (intent.resolveActivity(requireActivity().getPackageManager()) != null) {
requireContext().startActivity(chooserIntent);
} else {
IntentUtils.showErrorDialog(requireActivity());
}
}
}

View file

@ -1,47 +0,0 @@
package com.vectras.vm.file;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
public class FilePickerSettings {
Context context;
SharedPreferences sharedPreferences;
public FilePickerSettings(Context context) {
this.context = context;
sharedPreferences = context.getSharedPreferences("built_in_file_picker_settings", Context.MODE_PRIVATE);
}
public void lastPath(String path) {
sharedPreferences.edit().putString("lastPath", path).apply();
}
public String lastPath() {
return sharedPreferences.getString("lastPath", Environment.getExternalStorageDirectory().getAbsolutePath());
}
public void resume(boolean enabled) {
sharedPreferences.edit().putBoolean("resume", enabled).apply();
}
public boolean resume() {
return sharedPreferences.getBoolean("resume", true);
}
public void showHiddenFiles(boolean enabled) {
sharedPreferences.edit().putBoolean("showHiddenFiles", enabled).apply();
}
public boolean showHiddenFiles() {
return sharedPreferences.getBoolean("showHiddenFiles", true);
}
public void divider(boolean enabled) {
sharedPreferences.edit().putBoolean("divider", enabled).apply();
}
public boolean divider() {
return sharedPreferences.getBoolean("divider", false);
}
}

View file

@ -46,7 +46,6 @@ import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.AboutActivity;
import com.vectras.vm.AppConfig;
import com.vectras.vm.creator.VMCreatorActivity;
import com.vectras.vm.file.FilePickerDialog;
import com.vectras.vm.settings.Minitools;
import com.vectras.vm.R;
import com.vectras.vm.WebViewActivity;
@ -523,14 +522,7 @@ public class MainActivity extends AppCompatActivity implements RomStoreFragment.
startActivity(new Intent(this, Settings2Activity.class));
} else if (id == R.id.navigation_data_explorer) {
// startActivity(new Intent(this, DataExplorerActivity.class));
if (MainSettingsManager.getBuiltInFilePicker(this)) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
filePickerDialog.setHomeName(getString(R.string.app_name));
filePickerDialog.setLockHome(true);
filePickerDialog.browse(this, AppConfig.maindirpath);
} else {
FileUtils.openFolder(this, AppConfig.maindirpath);
}
FileUtils.openFolder(this, AppConfig.maindirpath);
} else if (id == R.id.navigation_item_donate) {
String tw = "https://www.patreon.com/VectrasTeam";
Intent w = new Intent(ACTION_VIEW);

View file

@ -6,8 +6,6 @@ import static com.vectras.vm.utils.LibraryChecker.isPackageInstalled2;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.termux.app.TermuxService;
@ -23,7 +21,6 @@ import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.PackageUtils;
import com.vectras.vm.x11.X11Activity;
import com.vectras.vterm.Terminal;
import com.vectras.vterm.Terminal2;
import java.io.File;
import java.util.HashSet;
@ -89,32 +86,8 @@ public class DisplaySystem {
R.drawable.desktop_24px,
true,
() -> {
String installCommand = "apk add " + necessaryPackage + " && echo \"Installed: " + necessaryPackage + "\"";
Terminal2 terminal2 = new Terminal2(context);
terminal2.setShowProgressDialog(true);
terminal2.execute(installCommand, new Terminal2.Terminal2Callback() {
@Override
public void onRunning(String command, String newLine) {
// Nothing to do.
}
@Override
public void onFinished(String command, String log, int status) {
new Handler(Looper.getMainLooper()).post(() -> {
if (status == terminal2.SUCCESS) {
launchX11(context, isKill);
} else {
DialogUtils.oopsDialog(context, log);
}
});
}
@Override
public void onError(String command, Exception exception) {
new Handler(Looper.getMainLooper()).post(() -> DialogUtils.oopsDialog(context, exception.getMessage()));
}
});
String installCommand = "apk add " + necessaryPackage;
new Terminal(context).executeShellCommand(installCommand, true, true, context.getString(R.string.just_a_moment), context);
},
null,
null
@ -143,9 +116,7 @@ public class DisplaySystem {
}
public static void startDesktop(Context context) {
Terminal2 terminal2 = new Terminal2(context);
terminal2.setDefaultShellBash();
terminal2.execute("export DISPLAY=:0 && fluxbox > /dev/null");
new Terminal(context).executeShellCommand2("export DISPLAY=:0 && fluxbox > /dev/null", false, context);
}
public static void startTermuxX11(Context context) {

View file

@ -35,7 +35,6 @@ import java.io.File;
public class MainStartVM {
public static final String TAG = "HomeStartVM";
public static final String TAG_FINISHED_WITHOUT_ERROR = "This VM has shut down.";
public static boolean skipIDEwithARM64DialogInStartVM = false;
public static boolean breakNow = false;
public static final Handler handlerForLaunch = new Handler(Looper.getMainLooper());
@ -51,7 +50,7 @@ public class MainStartVM {
public static String pendingVMID = "";
public static String pendingThumbnailFile = "";
public static boolean isLaunchFromPending = false;
public static String runCommandFormat = "%s";
public static String runCommandFormat = "export TMPDIR=/tmp && mkdir -p $TMPDIR/pulse && export XDG_RUNTIME_DIR=/tmp && chmod -R 775 $TMPDIR/pulse && pulseaudio --start --exit-idle-time=-1 > /dev/null 2>&1 && %s";
private static StartVmDialog dialog;
@ -298,7 +297,7 @@ public class MainStartVM {
) {
VMManager.isQemuStopedWithError = false;
String cleanUpCommand = " && echo \"" + TAG_FINISHED_WITHOUT_ERROR + "\"\nrm -r " + Config.getCacheVMPath(vmID);
String cleanUpCommand = "; rm -r " + Config.getCacheVMPath(vmID);
String finalCommand = VMManager.addAudioDevWav(vmID, String.format(runCommandFormat, env + cleanUpCommand));
@ -315,12 +314,11 @@ public class MainStartVM {
}
if (ServiceUtils.isServiceRunning(context, MainService.class)) {
MainService.startCommand(vmName, finalCommand, context);
MainService.startCommand(finalCommand, context);
} else {
Intent serviceIntent = new Intent(context, MainService.class);
MainService.activityContext = context;
MainService.env = finalCommand;
MainService.vmName = vmName;
MainService.CHANNEL_ID = vmName;
if (SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent);
@ -490,6 +488,6 @@ public class MainStartVM {
}
public static void setDefault() {
runCommandFormat = "%s";
runCommandFormat = "export TMPDIR=/tmp && mkdir -p $TMPDIR/pulse && export XDG_RUNTIME_DIR=/tmp && chmod -R 775 $TMPDIR/pulse && pulseaudio --start --exit-idle-time=-1 > /dev/null 2>&1 && %s";
}
}

View file

@ -1,8 +1,6 @@
package com.vectras.vm.main.core;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
@ -15,7 +13,6 @@ import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vterm.Terminal;
import com.vectras.vterm.Terminal2;
public class PendingCommand {
private static final String TAG = "PendingCommand";
@ -52,30 +49,9 @@ public class PendingCommand {
null
);
} else {
Terminal2 terminal2 = new Terminal2(activity);
terminal2.setShowProgressDialog(true);
terminal2.execute(command, new Terminal2.Terminal2Callback() {
@Override
public void onRunning(String command, String newLine) {
// Nothing to do.
}
@Override
public void onFinished(String command, String log, int status) {
new Handler(Looper.getMainLooper()).post(() -> {
if (status == terminal2.SUCCESS) {
Toast.makeText(activity, activity.getResources().getString(R.string.done), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(activity, activity.getResources().getString(R.string.an_error_occurred_while_creating_the_virtual_drive), Toast.LENGTH_LONG).show();
}
});
}
@Override
public void onError(String command, Exception exception) {
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(activity, activity.getResources().getString(R.string.an_error_occurred_while_creating_the_virtual_drive), Toast.LENGTH_LONG).show());
}
});
Terminal _vterm = new Terminal(activity);
_vterm.executeShellCommand2(command, false, activity);
Toast.makeText(activity, activity.getResources().getString(R.string.done), Toast.LENGTH_LONG).show();
}
command = "";

View file

@ -3,7 +3,6 @@ package com.vectras.vm.main.core;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
@ -93,38 +92,31 @@ public class StartVmDialog {
boolean isVmRuning = VMManager.isVMRunning(activity, vmId);
if (!isVmRuning) {
new Handler(Looper.getMainLooper()).post(() -> {
isShuttingDown = false;
dismiss();
});
} else {
while (true) {
Config.vmID = vmId;
while (isVmRuning) {
Config.vmID = vmId;
isVmRuning = VMManager.isVMRunning(activity, vmId);
isVmRuning = VMManager.isVMRunning(activity, vmId);
QmpSender.shutdown();
QmpSender.shutdown();
if (!isVmRuning || VMManager.isQemuStopedWithError || triedCount >= MAX_TRY) {
if (triedCount < MAX_TRY) FileUtils.delete(Config.getLocalQMPSocketPath(vmId));
if (!isVmRuning || VMManager.isQemuStopedWithError || triedCount == MAX_TRY) {
if (triedCount < MAX_TRY) FileUtils.delete(Config.getLocalQMPSocketPath(vmId));
new Handler(Looper.getMainLooper()).post(() -> {
isShuttingDown = false;
dismiss();
});
new Handler(Looper.getMainLooper()).post(() -> {
isShuttingDown = false;
dismiss();
});
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
triedCount++;
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
triedCount++;
}
}).start();
});
@ -134,7 +126,7 @@ public class StartVmDialog {
.setCancelable(false)
.create();
if (!activity.isFinishing() && !activity.isDestroyed()) progressDialog.show();
progressDialog.show();
}
public void setStatus(String status) {

View file

@ -34,7 +34,6 @@ import com.vectras.vm.manager.QmpSender;
import com.vectras.vm.utils.CommandUtils;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vterm.Terminal;
import com.vectras.vterm.Terminal2;
import java.io.File;
import java.util.Locale;
@ -230,10 +229,10 @@ public class SystemMonitorFragment extends Fragment {
binding.tvQemuarch.setText(getString(R.string.arch) + " " + currentArch + ".");
executor.execute(() -> {
String qemuVersionName = CommandUtils.getQemuVersionName(requireContext());
String qemuVersionName = CommandUtils.getQemuVersionName();
if (!isAdded()) return;
String result = new Terminal2(requireContext()).executeOnThisThread("ps -e command && echo \"psendhere\" && cat /proc/cpuinfo");
String result = Terminal.executeShellCommandWithResult("ps -e command && echo \"psendhere\" && cat /proc/cpuinfo", requireActivity());
if (!isAdded()) return;
requireActivity().runOnUiThread(() -> {

View file

@ -3,15 +3,9 @@ package com.vectras.vm.main.vms;
import com.google.gson.annotations.SerializedName;
public class DataMainRoms {
public String vmID = "";
@SerializedName(
value = "arch",
alternate = { "imgArch" }
)
public String itemArch = "";
// Personalize
public int cpu = 0;
public int cores = 0;
public int threads = 0;
@SerializedName(
value = "icon",
@ -25,17 +19,11 @@ public class DataMainRoms {
)
public String itemName = "";
// Board
public int machine = 0;
public boolean nvirt; // Nested virtualization
public int cpu = 0;
public int cores = 0;
public int threads = 0;
public boolean battery;
// Storage
@SerializedName(
value = "arch",
alternate = { "imgArch" }
)
public String itemArch = "";
@SerializedName(
value = "drive",
@ -45,6 +33,11 @@ public class DataMainRoms {
public String hd1 = "";
@SerializedName(
value = "qemu",
alternate = { "imgExtra" }
)
public String itemExtra = "";
@SerializedName(
value = "cdrom",
@ -54,40 +47,25 @@ public class DataMainRoms {
public String cdrom1 = "";
public String fda = "";
public String fdb = "";
public boolean sharedFolder = false;
public boolean sharedFolder;
public String vmID = "";
// Network
public int networkCard = 0;
// Firmware
public int qmpPort = 0;
public int bootFrom = 0;
public boolean isShowBootMenu;
public boolean isShowBootMenu = false;
public boolean isUseLocalTime = true;
public boolean isUseUefi;
public boolean isUseUefi = false;
public boolean isUseDefaultBios = true;
// Advanced
@SerializedName(
value = "qemu",
alternate = { "imgExtra" }
)
public String itemExtra = "";
// Deprecated
@Deprecated
public int qmpPort = 0;
public boolean battery = false;
}

View file

@ -6,7 +6,6 @@ import com.vectras.vm.setupwizard.SetupFeatureCore;
import com.vectras.vm.utils.DeviceUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vterm.Terminal;
import com.vectras.vterm.Terminal2;
import java.io.File;
@ -52,7 +51,7 @@ public class BatteryEmulatorManager {
FileUtils.writeToFile(vmTemp.getAbsolutePath(), "battery.asl", batteryAsl);
if (FileUtils.isFileExists(VmFileManager.getTempPath(context, vmId, "battery.asl"))) {
String respond = new Terminal2(context).executeOnThisThread("cd " + vmTemp.getAbsolutePath() + " && iasl battery.asl && echo Compiled");
String respond = Terminal.executeShellCommandWithResult("cd " + vmTemp.getAbsolutePath() + " && iasl battery.asl && echo Compiled", context);
//Log.d(TAG, respond);
return respond.contains("Compiled");
} else {

View file

@ -10,7 +10,6 @@ import com.vectras.vm.utils.ClipboardUltils;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.ProgressDialog;
import com.vectras.vterm.Terminal;
import com.vectras.vterm.Terminal2;
public class HostSharedFolder {
public static final String TAG = "HostSharedFolder";
@ -26,16 +25,13 @@ public class HostSharedFolder {
new Thread(() -> {
boolean isRuning;
if (Terminal.executeShellCommandWithResult("pgrep -f 'http.server 19000'", context).isEmpty()) {
if (!Terminal.executeShellCommandWithResult("which python3", context).contains("python3"))
Terminal.executeShellCommandWithResult("apk add python3", context);
Terminal2 terminal2 = new Terminal2(context);
startCommand(context);
if (terminal2.executeOnThisThread("pgrep -f 'http.server 19000'").isEmpty()) {
if (!terminal2.executeOnThisThread("which python3").contains("python3"))
terminal2.executeOnThisThread("apk add python3");
new Terminal2(context).execute("python3 -m http.server 19000 --bind 127.0.0.1 --directory " + SHARED_DIR);
isRuning = !terminal2.executeOnThisThread("sleep 1; pgrep -f 'http.server 19000'").isEmpty();
isRuning = !Terminal.executeShellCommandWithResult("sleep 1; pgrep -f 'http.server 19000'", context).isEmpty();
} else {
isRuning = true;
}
@ -65,4 +61,9 @@ public class HostSharedFolder {
});
}).start();
}
public static void startCommand(Context _context) {
Terminal vterm = new Terminal(_context);
vterm.executeShellCommand2("python3 -m http.server 19000 --bind 127.0.0.1 --directory " + SHARED_DIR, false, null);
}
}

View file

@ -3,19 +3,7 @@ package com.vectras.vm.manager;
import java.util.regex.Pattern;
public class ParamManager {
public static boolean hasMachine(String param) {
return Pattern.compile("(?<![\\w-])--?(M|machine)\\s+[a-zA-Z0-9._-]+").matcher(param).find();
}
public static boolean hasCpu(String param) {
return Pattern.compile("(?<![\\w-])--?cpu\\s+[a-zA-Z0-9_-]+").matcher(param).find();
}
public static boolean hasSmp(String param) {
return Pattern.compile("(?<![\\w-])--?smp\\s+[a-zA-Z0-9,=]+").matcher(param).find();
}
public static boolean hasMemory(String param) {
return Pattern.compile("(?<![\\w-])--?m\\s+(\\d+)([a-zA-Z]*)").matcher(param).find();
return Pattern.compile("(?<![\\\\w-])--?m\\s+(\\d+)([a-zA-Z]*)").matcher(param).find();
}
}

View file

@ -2,10 +2,10 @@ package com.vectras.vm.manager;
import android.content.Context;
import com.vectras.vterm.Terminal2;
import com.vectras.vterm.Terminal;
public class ProcessManager {
public static boolean isQemuRunning(Context context) {
return new Terminal2(context).executeOnThisThread("ps -e").contains("qemu-system-");
return Terminal.executeShellCommandWithResult("ps -e", context).contains("qemu-system-");
}
}

View file

@ -4,14 +4,14 @@ import android.content.Context;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.settings.ItemSettingsSelector;
import com.vectras.vterm.Terminal2;
import com.vectras.vterm.Terminal;
public class QemuManager {
public static final int DEFAULT_REFRESH_RATE = 60;
public static final int DEFAULT_LOW_REFRESH_RATE = 30;
public static boolean isSupportSetRefreshRate(Context context) {
return new Terminal2(context).executeOnThisThread(getQemuExecutableFile(context) + " -vnc help").contains("refresh-rate");
return Terminal.executeShellCommandWithResult(getQemuExecutableFile(context) + " -vnc help", context).contains("refresh-rate");
}
public static boolean isSupportAcpiTable(Context context) {

View file

@ -363,7 +363,7 @@ public class QmpSender {
public static String changeDevice(String deviceId, String filePath) {
if (filePath.trim().isEmpty()) return ejectDevice(deviceId);
return send("change " + deviceId + " \"" + filePath + "\"");
return send("change " + deviceId + " " + filePath);
}
public static void quickEjectDevice(Context context, String deviceId) {

View file

@ -1,176 +0,0 @@
package com.vectras.vm.manager;
import android.androidVNC.VncCanvas;
import android.util.Log;
import android.view.View;
import com.vectras.vm.R;
public class VNCKeyManager {
final String TAG = "VNCKeyManager";
public static final int TRACK_TAG = 99;
public static final int DEL_KEY_CODE = 0xFFFF;
public static final int SHIFT_LEFT_KEY_CODE = 0xFFE1;
public static final int CTRL_LEFT_KEY_CODE = 0xFFE3;
public static final int ALT_LEFT_KEY_CODE = 0xFFE9;
public static final int WIN_LEFT_KEY_CODE = 0xFFEB;
public int holdMarksCollector = 0;
VncCanvas vncCanvas;
View shiftButtonView;
View ctrlButtonView;
View altButtonView;
View winButtonView;
public VNCKeyManager(VncCanvas vncCanvas) {
this.vncCanvas = vncCanvas;
}
public void setButtons(View shiftButtonView, View ctrlButtonView, View altButtonView, View winButtonView) {
this.shiftButtonView = shiftButtonView;
this.ctrlButtonView = ctrlButtonView;
this.altButtonView = altButtonView;
this.winButtonView = winButtonView;
}
public void reset() {
Log.d(TAG, "reset");
isHoldWinKey = false;
isHoldAltKey = false;
isHoldCtrlKey = false;
isHoldShiftKey = false;
updateButton(shiftButtonView, false);
updateButton(ctrlButtonView, false);
updateButton(altButtonView, false);
updateButton(winButtonView, false);
holdMarksCollector = 0;
if (vncCanvas == null || !vncCanvas.isAttachedToWindow()) return;
vncCanvas.metaStateCollector = 0;
vncCanvas.sendMetaKey1Up(SHIFT_LEFT_KEY_CODE, holdMarksCollector);
vncCanvas.sendMetaKey1Up(CTRL_LEFT_KEY_CODE, holdMarksCollector);
vncCanvas.sendMetaKey1Up(ALT_LEFT_KEY_CODE, holdMarksCollector);
vncCanvas.sendMetaKey1Up(WIN_LEFT_KEY_CODE, holdMarksCollector);
}
public void updateButton(View button, boolean isDown) {
if (button != null)
button.setBackgroundResource(isDown ? R.drawable.controls_button2 : R.drawable.controls_button1);
}
boolean isPauseCheckKeyChanged = false;
public void onKeyChanged(int keyCode, boolean isDown, int flags) {
if (isPauseCheckKeyChanged && isDown) {
isPauseCheckKeyChanged = false;
return;
}
if (
keyCode != SHIFT_LEFT_KEY_CODE &&
keyCode != CTRL_LEFT_KEY_CODE &&
keyCode != ALT_LEFT_KEY_CODE &&
keyCode != WIN_LEFT_KEY_CODE
) {
reset();
}
isPauseCheckKeyChanged = false;
}
private void onChange() {
isPauseCheckKeyChanged = true;
if (vncCanvas != null && vncCanvas.isAttachedToWindow()) vncCanvas.metaStateCollector = holdMarksCollector;
}
// SHIFT
boolean isHoldShiftKey;
public void shiftKey() {
if (isHoldShiftKey) {
holdMarksCollector &= ~VncCanvas.SHIFT_MASK;
vncCanvas.sendMetaKey1Up(SHIFT_LEFT_KEY_CODE, holdMarksCollector);
} else {
holdMarksCollector |= VncCanvas.SHIFT_MASK;
vncCanvas.sendMetaKey1Down(SHIFT_LEFT_KEY_CODE, holdMarksCollector);
}
isHoldShiftKey = !isHoldShiftKey;
updateButton(shiftButtonView, isHoldShiftKey);
onChange();
}
// CTRL
boolean isHoldCtrlKey;
public void ctrlKey() {
if (isHoldCtrlKey) {
holdMarksCollector &= ~VncCanvas.CTRL_MASK;
vncCanvas.sendMetaKey1Up(CTRL_LEFT_KEY_CODE, holdMarksCollector);
} else {
holdMarksCollector |= VncCanvas.CTRL_MASK;
vncCanvas.sendMetaKey1Down(CTRL_LEFT_KEY_CODE, holdMarksCollector);
}
isHoldCtrlKey = !isHoldCtrlKey;
updateButton(ctrlButtonView, isHoldCtrlKey);
onChange();
}
// CTRL
boolean isHoldAltKey;
public void altKey() {
if (isHoldAltKey) {
holdMarksCollector &= ~VncCanvas.ALT_MASK;
vncCanvas.sendMetaKey1Up(ALT_LEFT_KEY_CODE, holdMarksCollector);
} else {
holdMarksCollector |= VncCanvas.ALT_MASK;
vncCanvas.sendMetaKey1Down(ALT_LEFT_KEY_CODE, holdMarksCollector);
}
isHoldAltKey = !isHoldAltKey;
updateButton(altButtonView, isHoldAltKey);
onChange();
}
// WIN
boolean isHoldWinKey;
public void winKey() {
if (isHoldWinKey) {
holdMarksCollector &= ~VncCanvas.META_MASK;
vncCanvas.sendMetaKey1Up(WIN_LEFT_KEY_CODE, holdMarksCollector);
} else {
holdMarksCollector |= VncCanvas.META_MASK;
vncCanvas.sendMetaKey1Down(WIN_LEFT_KEY_CODE, holdMarksCollector);
}
isHoldWinKey = !isHoldWinKey;
updateButton(winButtonView, isHoldWinKey);
onChange();
}
// DELETE
public void deleteKey() {
vncCanvas.sendMetaKey1(DEL_KEY_CODE, holdMarksCollector);
onChange();
}
}

View file

@ -5,7 +5,7 @@ import android.util.Log;
import com.vectras.qemu.Config;
import com.vectras.vm.VectrasApp;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.sound.StreamAudio;
import com.vectras.vm.utils.StreamAudio;
public class VmAudioManager {
private static final String TAG = "VmAudioManager";

View file

@ -5,7 +5,6 @@ import android.androidVNC.VncCanvas;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@ -27,14 +26,13 @@ import com.vectras.vm.AppConfig;
import com.vectras.vm.R;
import com.vectras.vm.VMManager;
import com.vectras.vm.databinding.DialogChangeRemovableDevicesBinding;
import com.vectras.vm.file.FilePickerDialog;
import com.vectras.vm.main.core.DisplaySystem;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.settings.VNCSettingsActivity;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.ProgressDialog;
import com.vectras.vm.sound.StreamAudio;
import com.vectras.vm.utils.StreamAudio;
import com.vectras.vm.x11.X11Activity;
import java.io.File;
@ -56,8 +54,6 @@ public class VmControllerDialog extends DialogFragment {
public VncCanvas vncCanvas;
public View screenshotFrame;
float lastVolume;
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
@ -196,37 +192,27 @@ public class VmControllerDialog extends DialogFragment {
if (isAdded() && (!(requireActivity() instanceof MainVNCActivity)) && (!(requireActivity() instanceof X11Activity))) {
if (streamAudio == null)
streamAudio = new StreamAudio(requireActivity().getApplicationContext());
if (!streamAudio.isPlaying()) {
binding.sliderVolume.setVisibility(View.GONE);
VmAudioManager.set(Config.vmID);
}
if (!streamAudio.isPlaying()) VmAudioManager.set(Config.vmID);
}
if (streamAudio == null || !isAdded() || audioFileSize == 0 || !(requireActivity() instanceof MainVNCActivity) && !(requireActivity() instanceof X11Activity) && !VmAudioManager.currentVmId.equals(Config.vmID)
if (streamAudio == null ||
!isAdded() ||
audioFileSize == 0 ||
(isAdded() && (!(requireActivity() instanceof MainVNCActivity)) && !(requireActivity() instanceof X11Activity) && !VmAudioManager.currentVmId.equals(Config.vmID))
) {
binding.lnMute.setVisibility(View.GONE);
binding.sliderVolume.setVisibility(View.GONE);
} else {
binding.sliderVolume.setValue(streamAudio.getVolume());
binding.sliderVolume.addOnChangeListener((slider, value, fromUser) -> streamAudio.setVolume(value));
if (isAdded() && requireActivity() instanceof X11Activity) {
if (!streamAudio.getFile().equals(VmFileManager.findAudioRaw(getContext(), Config.vmID)) || !streamAudio.isPlaying()) {
// binding.ivMute.setImageResource(R.drawable.volume_up_24px);
// binding.tvMute.setText(R.string.unmute);
binding.sliderVolume.setVisibility(View.GONE);
binding.ivMute.setImageResource(R.drawable.volume_up_24px);
binding.tvMute.setText(R.string.unmute);
}
} else if (!streamAudio.isPlaying()) {
// binding.ivMute.setImageResource(R.drawable.volume_up_24px);
// binding.tvMute.setText(R.string.unmute);
binding.sliderVolume.setVisibility(View.GONE);
binding.ivMute.setImageResource(R.drawable.volume_up_24px);
binding.tvMute.setText(R.string.unmute);
}
if (binding.sliderVolume.getVisibility() == View.VISIBLE) {
binding.lnMute.setVisibility(View.GONE);
} else {
binding.lnMute.setOnClickListener(v -> mute());
}
binding.lnMute.setOnClickListener(v -> mute());
}
if (infoBlock != null && (infoBlock.contains(QmpSender.DEFAULT_OPTICAL_DISC_1_ID)
@ -240,16 +226,7 @@ public class VmControllerDialog extends DialogFragment {
if (isHavingOpticalDisc() || isHavingSecondaryOpticalDisc()) {
if (isHavingOpticalDisc()) {
binding.lnCdrom.setOnClickListener(v -> {
if (MainSettingsManager.getBuiltInFilePicker(requireContext())) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
if (requireActivity() instanceof MainVNCActivity) filePickerDialog.setFixTextColor(true);
filePickerDialog.pick(requireActivity(), filePickerDialog.FIT_PICK_OPTICAL_FILE_MODE, (path -> handleIsoFile(Uri.fromFile(new File(path)))));
} else {
isoPicker.launch("*/*");
}
});
binding.lnCdrom.setOnClickListener(v -> isoPicker.launch("*/*"));
binding.ivEjectcdrom.setOnClickListener(v -> {
QmpSender.ejectOpticalDisc(requireActivity(), infoBlock);
@ -263,15 +240,7 @@ public class VmControllerDialog extends DialogFragment {
}
if (isHavingSecondaryOpticalDisc()) {
binding.lnSecondaryCdrom.setOnClickListener(v -> {
if (MainSettingsManager.getBuiltInFilePicker(requireContext())) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
if (requireActivity() instanceof MainVNCActivity) filePickerDialog.setFixTextColor(true);
filePickerDialog.pick(requireActivity(), filePickerDialog.FIT_PICK_OPTICAL_FILE_MODE, (path -> handleIsoFile2(Uri.fromFile(new File(path)))));
} else {
isoPickerSecondary.launch("*/*");
}
});
binding.lnSecondaryCdrom.setOnClickListener(v -> isoPickerSecondary.launch("*/*"));
binding.ivSecondaryEjectcdrom.setOnClickListener(v -> {
QmpSender.ejectSecondaryOpticalDisc(requireActivity(), infoBlock);
@ -313,15 +282,7 @@ public class VmControllerDialog extends DialogFragment {
}
if (infoBlock.contains(QmpSender.DEFAULT_FLOPPY_DISK_0_ID)) {
binding.lnFda.setOnClickListener(v -> {
if (MainSettingsManager.getBuiltInFilePicker(requireContext())) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
if (requireActivity() instanceof MainVNCActivity) filePickerDialog.setFixTextColor(true);
filePickerDialog.pick(requireActivity(), filePickerDialog.FIT_PICK_FLOPPY_FILE_MODE, (path -> handleFloppyAFile(Uri.fromFile(new File(path)))));
} else {
floppyAPicker.launch("*/*");
}
});
binding.lnFda.setOnClickListener(v -> floppyAPicker.launch("*/*"));
binding.ivEjectfda.setOnClickListener(v -> {
QmpSender.ejectFloppyDiskA(requireActivity());
@ -336,15 +297,7 @@ public class VmControllerDialog extends DialogFragment {
}
if (infoBlock.contains(QmpSender.DEFAULT_FLOPPY_DISK_1_ID)) {
binding.lnFdb.setOnClickListener(v -> {
if (MainSettingsManager.getBuiltInFilePicker(requireContext())) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
if (requireActivity() instanceof MainVNCActivity) filePickerDialog.setFixTextColor(true);
filePickerDialog.pick(requireActivity(), filePickerDialog.FIT_PICK_FLOPPY_FILE_MODE, (path -> handleFloppyBFile(Uri.fromFile(new File(path)))));
} else {
floppyBPicker.launch("*/*");
}
});
binding.lnFdb.setOnClickListener(v -> floppyBPicker.launch("*/*"));
binding.ivEjectfdb.setOnClickListener(v -> {
QmpSender.ejectFloppyDiskB(requireActivity());
@ -359,15 +312,7 @@ public class VmControllerDialog extends DialogFragment {
}
if (infoBlock.contains(QmpSender.DEFAULT_MEMORY_CARD_ID)) {
binding.lnSd.setOnClickListener(v -> {
if (MainSettingsManager.getBuiltInFilePicker(requireContext())) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
if (requireActivity() instanceof MainVNCActivity) filePickerDialog.setFixTextColor(true);
filePickerDialog.pick(requireActivity(), filePickerDialog.DISK_FILE, (path -> handleMemoryCardFile(Uri.fromFile(new File(path)))));
} else {
memoryCardPicker.launch("*/*");
}
});
binding.lnSd.setOnClickListener(v -> memoryCardPicker.launch("*/*"));
binding.ivEjectsd.setOnClickListener(v -> {
QmpSender.ejectMemoryCard(requireActivity());
@ -393,10 +338,6 @@ public class VmControllerDialog extends DialogFragment {
if (isAdded() && requireActivity() instanceof MainVNCActivity mainVNCActivity) {
binding.sliderBrightness.setValue(vncCanvas.getAlpha() * 100);
binding.sliderBrightness.addOnChangeListener((slider, value, fromUser) -> vncCanvas.setAlpha(value / 100));
binding.lnRefresh.setOnClickListener(v -> {
requireActivity().startActivity(new Intent(requireActivity(), MainVNCActivity.class));
requireActivity().overridePendingTransition(0, 0);
@ -528,8 +469,6 @@ public class VmControllerDialog extends DialogFragment {
} else {
binding.lnUserInterface.setVisibility(View.GONE);
}
if (streamAudio != null) lastVolume = streamAudio.getVolume();
});
}).start();
@ -548,13 +487,6 @@ public class VmControllerDialog extends DialogFragment {
if (onDismissCallback != null) {
onDismissCallback.run();
}
if (streamAudio != null && streamAudio.getVolume() == 0) {
if (lastVolume == 0) lastVolume = 1f;
streamAudio.stop();
streamAudio.setNextPlayVolume(lastVolume);
}
}
private void takeScreenshot() {
@ -602,34 +534,29 @@ public class VmControllerDialog extends DialogFragment {
if (isAdded() && requireActivity() instanceof X11Activity) {
if (streamAudio.isPlaying() && streamAudio.getFile().equals(VmFileManager.findAudioRaw(getContext(), Config.vmID))) {
streamAudio.stop();
// binding.ivMute.setImageResource(R.drawable.volume_up_24px);
// binding.tvMute.setText(R.string.unmute);
binding.ivMute.setImageResource(R.drawable.volume_up_24px);
binding.tvMute.setText(R.string.unmute);
} else {
if (!streamAudio.getFile().equals(VmFileManager.findAudioRaw(getContext(), Config.vmID))) {
streamAudio.stop();
streamAudio.setFile(VmFileManager.findAudioRaw(getContext(), Config.vmID));
}
streamAudio.play();
// binding.ivMute.setImageResource(R.drawable.volume_off_24px);
// binding.tvMute.setText(R.string.mute);
binding.lnMute.setVisibility(View.GONE);
binding.sliderVolume.setVisibility(View.VISIBLE);
binding.ivMute.setImageResource(R.drawable.volume_off_24px);
binding.tvMute.setText(R.string.mute);
}
} else if (streamAudio.isPlaying()) {
streamAudio.stop();
// binding.ivMute.setImageResource(R.drawable.volume_up_24px);
// binding.tvMute.setText(R.string.unmute);
binding.ivMute.setImageResource(R.drawable.volume_up_24px);
binding.tvMute.setText(R.string.unmute);
} else {
if (isAdded() && requireActivity() instanceof MainVNCActivity) {
streamAudio.play();
} else {
VmAudioManager.stream(Config.vmID);
}
// binding.ivMute.setImageResource(R.drawable.volume_off_24px);
// binding.tvMute.setText(R.string.mute);
binding.lnMute.setVisibility(View.GONE);
binding.sliderVolume.setVisibility(View.VISIBLE);
binding.ivMute.setImageResource(R.drawable.volume_off_24px);
binding.tvMute.setText(R.string.mute);
}
}
@ -644,134 +571,117 @@ public class VmControllerDialog extends DialogFragment {
}
private final ActivityResultLauncher<String> isoPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), this::handleIsoFile);
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri != null) {
try {
new Thread(() -> {
String path = FileUtils.getPath(getContext(), uri);
public void handleIsoFile(Uri uri) {
if (uri != null) {
try {
new Thread(() -> {
String path = FileUtils.getPath(getContext(), uri);
if (path == null) {
showErrorSelectedFileDialog();
dismiss();
return;
}
if (path == null) {
File selectedFilePath = new File(path);
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeOpticalDisc(requireActivity(), selectedFilePath.getAbsolutePath(), infoBlock);
dismiss();
});
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
dismiss();
return;
}
File selectedFilePath = new File(path);
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeOpticalDisc(requireActivity(), selectedFilePath.getAbsolutePath(), infoBlock);
dismiss();
});
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
dismiss();
}
}
}
}
});
private final ActivityResultLauncher<String> isoPickerSecondary =
registerForActivityResult(new ActivityResultContracts.GetContent(), this::handleIsoFile2);
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri != null) {
try {
new Thread(() -> {
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
public void handleIsoFile2(Uri uri) {
if (uri != null) {
try {
new Thread(() -> {
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeSecondaryOpticalDisc(requireActivity(), selectedFilePath.getAbsolutePath(), infoBlock);
dismiss();
});
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeSecondaryOpticalDisc(requireActivity(), selectedFilePath.getAbsolutePath(), infoBlock);
dismiss();
});
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
dismiss();
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
dismiss();
}
}
}
}
});
private final ActivityResultLauncher<String> floppyAPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), this::handleFloppyAFile);
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri != null) {
try {
new Thread(() -> {
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
public void handleFloppyAFile(Uri uri) {
if (uri != null) {
try {
new Thread(() -> {
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeFloppyDiskA(requireActivity(), selectedFilePath.getAbsolutePath());
dismiss();
});
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeFloppyDiskA(requireActivity(), selectedFilePath.getAbsolutePath());
dismiss();
});
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
dismiss();
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
dismiss();
}
}
}
}
});
private final ActivityResultLauncher<String> floppyBPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), this::handleFloppyBFile);
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri != null) {
try {
new Thread(() -> {
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
public void handleFloppyBFile(Uri uri) {
if (uri != null) {
try {
new Thread(() -> {
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeFloppyDiskB(requireActivity(), selectedFilePath.getAbsolutePath());
dismiss();
});
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeFloppyDiskB(requireActivity(), selectedFilePath.getAbsolutePath());
dismiss();
});
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
dismiss();
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
dismiss();
}
}
}
}
});
private final ActivityResultLauncher<String> memoryCardPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), this::handleMemoryCardFile);
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
if (uri != null) {
try {
new Thread(() -> {
File selectedFilePath = new File(Objects.requireNonNull(FileUtils.getPath(getContext(), uri)));
public void handleMemoryCardFile(Uri uri) {
if (uri != null) {
try {
new Thread(() -> {
String filePath = FileUtils.getPath(getContext(), uri);
if (filePath == null) {
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeMemoryCard(requireActivity(), selectedFilePath.getAbsolutePath());
dismiss();
});
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
return;
dismiss();
}
File selectedFilePath = new File(filePath);
if (isAdded()) {
requireActivity().runOnUiThread(() -> {
QmpSender.changeMemoryCard(requireActivity(), selectedFilePath.getAbsolutePath());
dismiss();
});
}
}).start();
} catch (Exception e) {
showErrorSelectedFileDialog();
dismiss();
}
}
}
}
});
private void showErrorSelectedFileDialog() {
DialogUtils.oneDialog(requireActivity(),

View file

@ -3,6 +3,7 @@ package com.vectras.vm.manager;
import android.app.Activity;
import com.vectras.vm.R;
import com.vectras.vm.creator.VMCreatorSelector;
import com.vectras.vm.utils.UniversalPickerDialog;
import java.util.ArrayList;

View file

@ -1,195 +0,0 @@
package com.vectras.vm.settings;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import com.vectras.vm.R;
import com.vectras.vm.databinding.ActivityEqualizerBinding;
import com.vectras.vm.sound.AudioSettingsData;
import com.vectras.vm.sound.SoundEffect;
import java.text.DecimalFormat;
import java.util.Objects;
public class EqualizerActivity extends AppCompatActivity {
ActivityEqualizerBinding binding;
AudioSettingsData audioSettingsData;
float[] lastValues = new float[5];
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.undo) {
binding.sliderUpperTreble.setValue(lastValues[0]);
binding.sliderTreble.setValue(lastValues[1]);
binding.sliderMid.setValue(lastValues[2]);
binding.sliderBass.setValue(lastValues[3]);
binding.sliderLowBass.setValue(lastValues[4]);
return true;
} else if (id == R.id.reset) {
binding.sliderUpperTreble.setValue(0);
binding.sliderTreble.setValue(0);
binding.sliderMid.setValue(0);
binding.sliderBass.setValue(0);
binding.sliderLowBass.setValue(0);
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.equalizer_menu, menu);
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
binding = ActivityEqualizerBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
binding.toolbar.setNavigationOnClickListener(view -> finish());
initialize();
}
@Override
public void onPause() {
super.onPause();
if (audioSettingsData != null) {
audioSettingsData.setEqualizerEnabled(binding.swEnabled.isChecked());
audioSettingsData.setUpperTreble(binding.sliderUpperTreble.getValue());
audioSettingsData.setTreble(binding.sliderTreble.getValue());
audioSettingsData.setMid(binding.sliderMid.getValue());
audioSettingsData.setBass(binding.sliderBass.getValue());
audioSettingsData.setLowBass(binding.sliderLowBass.getValue());
}
}
private void initialize() {
SoundEffect soundEffect = new SoundEffect(this, 0);
short bands = soundEffect.equalizer.getNumberOfBands();
if (bands < 2) {
binding.lnUnsupport.setVisibility(View.VISIBLE);
binding.appbar.setVisibility(View.GONE);
binding.lnEnabled.setVisibility(View.GONE);
binding.lnAllOptions.setVisibility(View.GONE);
binding.btnExit.setOnClickListener(v -> finish());
return;
}
audioSettingsData = new AudioSettingsData(this);
lastValues[0] = audioSettingsData.getUpperTreble();
lastValues[1] = audioSettingsData.getTreble();
lastValues[2] = audioSettingsData.getMid();
lastValues[3] = audioSettingsData.getBass();
lastValues[4] = audioSettingsData.getLowBass();
// 1dB = 100mB
int minBandLevelRange = soundEffect.getMinBandLevelRange() / 100;
int maxBandLevelRange = soundEffect.getMaxBandLevelRange() / 100;
if (bands > 4) {
binding.sliderLowBass.setValueFrom(minBandLevelRange);
binding.sliderLowBass.setValueTo(maxBandLevelRange);
binding.sliderLowBass.setValue(audioSettingsData.getLowBass());
binding.tvLowBassValue.setText(getFormattedValue(binding.sliderLowBass.getValue()));
binding.sliderLowBass.addOnChangeListener((slider, value, fromUser) -> binding.tvLowBassValue.setText(getFormattedValue(value)));
} else {
binding.lnLowBass.setVisibility(View.GONE);
binding.tvUpperTreble.setText(R.string.upper_treble);
binding.tvTreble.setText(R.string.treble);
binding.tvMid.setText(R.string.bass);
binding.tvBass.setText(R.string.low_bass);
}
if (bands > 3) {
binding.sliderBass.setValueFrom(minBandLevelRange);
binding.sliderBass.setValueTo(maxBandLevelRange);
binding.sliderBass.setValue(audioSettingsData.getBass());
binding.tvBassValue.setText(getFormattedValue(binding.sliderBass.getValue()));
binding.sliderBass.addOnChangeListener((slider, value, fromUser) -> binding.tvBassValue.setText(getFormattedValue(value)));
} else {
binding.lnBass.setVisibility(View.GONE);
binding.tvUpperTreble.setText(R.string.treble);
binding.tvTreble.setText(R.string.mid);
binding.tvMid.setText(R.string.bass);
}
if (bands > 2) {
binding.sliderMid.setValueFrom(minBandLevelRange);
binding.sliderMid.setValueTo(maxBandLevelRange);
binding.sliderMid.setValue(audioSettingsData.getMid());
binding.tvMidValue.setText(getFormattedValue(binding.sliderMid.getValue()));
binding.sliderMid.addOnChangeListener((slider, value, fromUser) -> binding.tvMidValue.setText(getFormattedValue(value)));
} else {
binding.lnMid.setVisibility(View.GONE);
binding.tvUpperTreble.setText(R.string.treble);
binding.tvTreble.setText(R.string.bass);
}
binding.sliderUpperTreble.setValueFrom(minBandLevelRange);
binding.sliderUpperTreble.setValueTo(maxBandLevelRange);
binding.sliderTreble.setValueFrom(minBandLevelRange);
binding.sliderTreble.setValueTo(maxBandLevelRange);
binding.sliderUpperTreble.setValue(audioSettingsData.getUpperTreble());
binding.sliderTreble.setValue(audioSettingsData.getTreble());
binding.tvUpperTrebleValue.setText(getFormattedValue(binding.sliderUpperTreble.getValue()));
binding.tvTrebleValue.setText(getFormattedValue(binding.sliderTreble.getValue()));
binding.sliderUpperTreble.addOnChangeListener((slider, value, fromUser) -> binding.tvUpperTrebleValue.setText(getFormattedValue(value)));
binding.sliderTreble.addOnChangeListener((slider, value, fromUser) -> binding.tvTrebleValue.setText(getFormattedValue(value)));
binding.lnEnabled.setOnClickListener(v -> binding.swEnabled.toggle());
binding.swEnabled.setChecked(audioSettingsData.isEqualizerEnabled());
binding.swEnabled.setOnCheckedChangeListener((buttonView, isChecked) -> setEnabled(isChecked));
setEnabled(binding.swEnabled.isChecked());
}
private void setEnabled(boolean isEnabled) {
binding.lnAllOptions.setAlpha(isEnabled ? 1 : 0.5f);
binding.sliderUpperTreble.setEnabled(isEnabled);
binding.sliderTreble.setEnabled(isEnabled);
binding.sliderMid.setEnabled(isEnabled);
binding.sliderBass.setEnabled(isEnabled);
binding.sliderLowBass.setEnabled(isEnabled);
}
DecimalFormat decimalFormat = new DecimalFormat("#.#");
private String getFormattedValue(float value) {
return decimalFormat.format(value) + " dB";
}
}

View file

@ -1,65 +0,0 @@
package com.vectras.vm.settings;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.R;
import com.vectras.vm.databinding.ActivityFilePickerSettingsBinding;
import com.vectras.vm.file.FilePickerSettings;
import java.util.Objects;
public class FilePickerSettingsActivity extends AppCompatActivity {
ActivityFilePickerSettingsBinding binding;
FilePickerSettings settings;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_external_vnc_settings);
binding = ActivityFilePickerSettingsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
binding.toolbar.setNavigationOnClickListener(view -> finish());
initialize();
}
private void initialize() {
settings = new FilePickerSettings(this);
binding.swEnabled.setOnCheckedChangeListener((buttonView, isChecked) -> {
MainSettingsManager.setBuiltInFilePicker(this, isChecked);
uiController(isChecked);
});
binding.lnEnabled.setOnClickListener(v -> binding.swEnabled.toggle());
binding.swResume.setOnCheckedChangeListener((buttonView, isChecked) -> settings.resume(isChecked));
binding.lnResume.setOnClickListener(v -> binding.swResume.toggle());
binding.swDivider.setOnCheckedChangeListener((buttonView, isChecked) -> settings.divider(isChecked));
binding.lnDivider.setOnClickListener(v -> binding.swDivider.toggle());
binding.swShowHiddenFiles.setOnCheckedChangeListener((buttonView, isChecked) -> settings.showHiddenFiles(isChecked));
binding.lnShowHiddenFiles.setOnClickListener(v -> binding.swShowHiddenFiles.toggle());
binding.swResume.setChecked(settings.resume());
binding.swDivider.setChecked(settings.divider());
binding.swShowHiddenFiles.setChecked(settings.showHiddenFiles());
binding.swEnabled.setChecked(MainSettingsManager.getBuiltInFilePicker(this));
uiController(binding.swEnabled.isChecked());
}
private void uiController(boolean isEnabled) {
binding.lnAllOptions.setAlpha(isEnabled ? 1f : 0.5f);
binding.lnResume.setEnabled(isEnabled);
binding.lnDivider.setEnabled(isEnabled);
binding.lnShowHiddenFiles.setEnabled(isEnabled);
}
}

View file

@ -25,7 +25,7 @@ import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.AppConfig;
import com.vectras.vm.R;
import com.vectras.vm.VMManager;
import com.vectras.vm.creator.utils.VMCreatorSelector;
import com.vectras.vm.creator.VMCreatorSelector;
import com.vectras.vm.databinding.ActivityMinitoolsBinding;
import com.vectras.vm.main.MainActivity;
import com.vectras.vm.manager.FirmwareManager;
@ -287,7 +287,7 @@ public class Minitools extends AppCompatActivity {
FileUtils.delete(new File(getFilesDir().getAbsolutePath() + "/usr"));
runOnUiThread(() -> {
DialogUtils.safeDismiss(this, progressDialog);
progressDialog.dismiss();
Intent intent = new Intent();
intent.setClass(this, SetupWizard2Activity.class);
startActivity(intent);

View file

@ -31,7 +31,6 @@ public class Settings2Activity extends AppCompatActivity {
binding.lnTheme.setOnClickListener(v -> startActivity(new Intent(this, ThemeActivity.class)));
binding.lnNotification.setOnClickListener(v -> startActivity(new Intent(this, NotificationSettingsActivity.class)));
binding.lnSearch.setOnClickListener(v -> startActivity(new Intent(this, SearchSettingsActivity.class)));
binding.lnFilePicker.setOnClickListener(v -> startActivity(new Intent(this, FilePickerSettingsActivity.class)));
binding.lnSystem.setOnClickListener(v -> startActivity(new Intent(this, SystemSettingsActivity.class)));
binding.lnQemu.setOnClickListener(v -> {
@ -43,7 +42,5 @@ public class Settings2Activity extends AppCompatActivity {
binding.lnVnc.setOnClickListener(v -> startActivity(new Intent(this, VNCSettingsActivity.class)));
binding.lnX11.setOnClickListener(v -> startActivity(new Intent(this, X11DisplaySettingsActivity.class)));
binding.lnEqualizer.setOnClickListener(v -> startActivity(new Intent(this, EqualizerActivity.class)));
}
}

View file

@ -3,6 +3,7 @@ package com.vectras.vm.setupwizard;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import com.vectras.vm.R;

View file

@ -1,6 +1,9 @@
package com.vectras.vm.setupwizard;
import static android.content.Intent.ACTION_VIEW;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@ -10,8 +13,10 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.transition.TransitionManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import androidx.activity.OnBackPressedCallback;
import androidx.activity.result.ActivityResultLauncher;
@ -24,13 +29,15 @@ import com.anbui.elephant.retrofit2utils.Retrofit2Utils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.termux.app.TermuxActivity;
import com.termux.app.TermuxService;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.AppConfig;
import com.vectras.vm.R;
import com.vectras.vm.VMManager;
import com.vectras.vm.creator.utils.VMCreatorSelector;
import com.vectras.vm.creator.VMCreatorSelector;
import com.vectras.vm.databinding.ActivitySetupWizard2Binding;
import com.vectras.vm.databinding.SetupQemuDoneBinding;
import com.vectras.vm.databinding.SimpleLayoutListViewWithCheckBinding;
import com.vectras.vm.main.MainActivity;
import com.vectras.vm.utils.DeviceUtils;
import com.vectras.vm.utils.DialogUtils;
@ -41,9 +48,14 @@ import com.vectras.vm.utils.ListUtils;
import com.vectras.vm.utils.PermissionUtils;
import com.vectras.vm.utils.TarUtils;
import com.vectras.vm.utils.UIUtils;
import com.vectras.vterm.Terminal2;
import com.vectras.vterm.TerminalBottomSheetDialog;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;
@ -54,8 +66,6 @@ public class SetupWizard2Activity extends AppCompatActivity {
ActivitySetupWizard2Binding binding;
SetupQemuDoneBinding bindingFinalSteps;
public static final int ACTION_SYSTEM_UPDATE = 1;
public static final int ACTION_CORE_SYSTEM_UPDATE = 2;
int ACTION;
final int STEP_REQUEST_PERMISSION = 1;
final int STEP_EXTRACTING_SYSTEM_FILES = 2;
final int STEP_GETTING_DATA = 3;
@ -74,6 +84,7 @@ public class SetupWizard2Activity extends AppCompatActivity {
String downloadBootstrapsCommand = "";
String tarPath = "";
String progressText ="0%";
boolean isSystemUpdateMode = false;
boolean isExecutingCommand = false;
boolean isLibProotError = false;
boolean aria2Error = false;
@ -177,7 +188,7 @@ public class SetupWizard2Activity extends AppCompatActivity {
});
binding.btnTryAgain.setOnClickListener(v -> {
if (ACTION == ACTION_SYSTEM_UPDATE) {
if (isSystemUpdateMode) {
uiController(STEP_SYSTEM_UPDATE);
binding.btnSkipSystemUpdate.setVisibility(View.GONE);
} else if (isLibProotError) {
@ -221,22 +232,16 @@ public class SetupWizard2Activity extends AppCompatActivity {
uiController(STEP_EXTRACTING_SYSTEM_FILES);
new Thread(() -> {
VMManager.killallqemuprocesses(this);
if (ACTION == ACTION_CORE_SYSTEM_UPDATE) {
FileUtils.delete(getFilesDir().getAbsolutePath() + "/data");
FileUtils.delete(getFilesDir().getAbsolutePath() + "/distro");
FileUtils.delete(getFilesDir().getAbsolutePath() + "/usr");
}
FileUtils.delete(getFilesDir().getAbsolutePath() + "/data");
FileUtils.delete(getFilesDir().getAbsolutePath() + "/distro");
FileUtils.delete(getFilesDir().getAbsolutePath() + "/usr");
runOnUiThread(this::extractSystemFiles);
}).start();
});
if (getIntent().hasExtra("action")) {
ACTION = getIntent().getIntExtra("action", -1);
if (ACTION == ACTION_CORE_SYSTEM_UPDATE) {
uiController(STEP_SYSTEM_UPDATE);
binding.btnSkipSystemUpdate.setVisibility(View.GONE);
} else if (ACTION == ACTION_SYSTEM_UPDATE) {
if (getIntent().getIntExtra("action", -1) == ACTION_SYSTEM_UPDATE) {
isSystemUpdateMode = true;
uiController(STEP_SYSTEM_UPDATE);
}
}
@ -374,11 +379,6 @@ public class SetupWizard2Activity extends AppCompatActivity {
}
private void extractSystemFiles() {
if (ACTION == ACTION_SYSTEM_UPDATE) {
getDataForStandardSetup();
return;
}
uiController(STEP_EXTRACTING_SYSTEM_FILES);
executor.execute(() -> {
@ -423,7 +423,7 @@ public class SetupWizard2Activity extends AppCompatActivity {
}
}
new Handler(Looper.getMainLooper()).postDelayed(() -> {
if (ACTION == ACTION_SYSTEM_UPDATE) {
if (isSystemUpdateMode) {
startSetup();
} else {
uiController(STEP_SETUP_OPTIONS);
@ -431,7 +431,6 @@ public class SetupWizard2Activity extends AppCompatActivity {
}, 1000);
} else {
new Handler(Looper.getMainLooper()).postDelayed(() -> uiController(STEP_SETUP_OPTIONS), 1000);
Log.e("SetupWizard2Activity", "getDataForStandardSetup: " + error);
}
}));
}
@ -466,46 +465,32 @@ public class SetupWizard2Activity extends AppCompatActivity {
" apk update;" +
" echo \"Installing packages...\";" +
" apk add " + (DeviceUtils.is64bit() ? AppConfig.neededPkgs()
: AppConfig.neededPkgs32bit()) + ";";
: AppConfig.neededPkgs32bit()) + ";" +
" echo \"Downloading Qemu...\";";
if (ACTION == ACTION_SYSTEM_UPDATE) {
cmd += "echo \"Uninstalling...\";" +
" rm -f /usr/local/bin/qemu-*;" +
" rm -f /usr/share/applications/qemu.desktop;" +
" rm -f /usr/share/icons/hicolor/*/qemu.png;" +
" rm -rf /usr/share/qemu;" +
downloadBootstrapsCommand + ";" +
if (isCustomSetupMode) {
cmd += " tar -xzvf " + tarPath + " -C /;" +
" rm " + tarPath + ";" +
" chmod 775 /usr/local/bin/*;";
} else {
if (FileUtils.isFileExists(getFilesDir().getAbsolutePath() + "/distro/root/setup.tar.gz"))
FileUtils.delete(getFilesDir().getAbsolutePath() + "/distro/root/setup.tar.gz");
cmd += downloadBootstrapsCommand + ";" +
" echo \"Installing Qemu...\";" +
" tar -xzvf setup.tar.gz -C /;" +
" rm setup.tar.gz;" +
" chmod 775 /usr/local/bin/*;";
} else {
if (isCustomSetupMode) {
cmd += " echo \"Installing Qemu...\";" +
" tar -xzvf " + tarPath + " -C /;" +
" rm " + tarPath + ";" +
" chmod 775 /usr/local/bin/*;" +
" echo \"Just a sec...\";" +
" mkdir -p ~/.vnc && echo -e \"555555\\n555555\" | vncpasswd -f > ~/.vnc/passwd && chmod 0600 ~/.vnc/passwd;";
} else {
if (FileUtils.isFileExists(getFilesDir().getAbsolutePath() + "/distro/root/setup.tar.gz"))
FileUtils.delete(getFilesDir().getAbsolutePath() + "/distro/root/setup.tar.gz");
cmd += " echo \"Downloading Qemu...\";" +
downloadBootstrapsCommand + ";" +
" echo \"Installing Qemu...\";" +
" tar -xzvf setup.tar.gz -C /;" +
" rm setup.tar.gz;" +
" chmod 775 /usr/local/bin/*;" +
" echo \"Just a sec...\";" +
" mkdir -p ~/.vnc && echo -e \"555555\\n555555\" | vncpasswd -f > ~/.vnc/passwd && chmod 0600 ~/.vnc/passwd;";
}
}
cmd += " echo \"Installation successful! xssFjnj58Id\"";
cmd += " echo \"Just a sec...\";" +
" echo export TMPDIR=/tmp >> /etc/profile;" +
" mkdir -p $TMPDIR/pulse;" +
" echo export PULSE_SERVER=127.0.0.1 >> /etc/profile;" +
" mkdir -p ~/.vnc && echo -e \"555555\\n555555\" | vncpasswd -f > ~/.vnc/passwd && chmod 0600 ~/.vnc/passwd;" +
" echo \"Installation successful! xssFjnj58Id\"";
execute(cmd);
executeShellCommand(cmd);
});
}).start();
}
@ -541,17 +526,83 @@ public class SetupWizard2Activity extends AppCompatActivity {
}
});
private void execute(String command) {
Terminal2 terminal2 = new Terminal2(this);
terminal2.execute(command, new Terminal2.Terminal2Callback() {
@Override
public void onRunning(String command, String newLine) {
runOnUiThread(() -> appendTextAndScroll(newLine + "\n"));
}
public void executeShellCommand(String userCommand) {
isExecutingCommand = true;
new Thread(() -> {
try {
// Set up the process builder to start PRoot with environmental variables and commands
ProcessBuilder processBuilder = new ProcessBuilder();
@Override
public void onFinished(String command, String log, int status) {
if (status != terminal2.SUCCESS) {
// Adjust these environment variables as necessary for your app
String filesDir = getFilesDir().getAbsolutePath();
File tmpDir = new File(getFilesDir(), "usr/tmp");
// Setup environment for the PRoot process
processBuilder.environment().put("PROOT_TMP_DIR", tmpDir.getAbsolutePath());
processBuilder.environment().put("HOME", "/root");
processBuilder.environment().put("USER", "root");
processBuilder.environment().put("PATH", "/bin:/usr/bin:/sbin:/usr/sbin");
processBuilder.environment().put("TERM", "xterm-256color");
processBuilder.environment().put("TMPDIR", tmpDir.getAbsolutePath());
processBuilder.environment().put("SHELL", "/bin/sh");
String[] prootCommand = {
TermuxService.PREFIX_PATH + "/bin/proot", // PRoot binary path
"--kill-on-exit",
"--link2symlink",
"-0",
"-r", filesDir + "/distro", // Path to the rootfs
"-b", "/dev",
"-b", "/proc",
"-b", "/sys",
"-b", "/sdcard",
"-b", "/storage",
"-b", "/data",
"-w", "/root",
"/bin/sh",
"--login"// The shell to execute inside PRoot
};
processBuilder.command(prootCommand);
Process process = processBuilder.start();
// Get the input and output streams of the process
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
// Send user command to PRoot
writer.write(userCommand);
writer.newLine();
writer.flush();
writer.close();
// Read the input stream for the output of the command
String line;
while ((line = reader.readLine()) != null) {
final String outputLine = line;
runOnUiThread(() -> appendTextAndScroll(outputLine + "\n"));
}
// Read any errors from the error stream
while ((line = errorReader.readLine()) != null) {
final String errorLine = line;
runOnUiThread(() -> appendTextAndScroll(errorLine + "\n"));
}
// Clean up
reader.close();
errorReader.close();
// Wait for the process to finish
process.waitFor();
// Wait for the process to finish
int exitValue = process.waitFor();
// Check if the exit value indicates an error
if (exitValue != 0) {
isExecutingCommand = false;
if (aria2Error && downloadBootstrapsCommand.contains("aria2c")) {
runOnUiThread(() -> {
@ -560,22 +611,22 @@ public class SetupWizard2Activity extends AppCompatActivity {
});
} else {
runOnUiThread(() -> {
String toastMessage = "Command failed with exit code: " + status;
String toastMessage = "Command failed with exit code: " + exitValue;
appendTextAndScroll("Error: " + toastMessage + "\n");
uiController(STEP_ERROR, logs);
});
}
}
}
@Override
public void onError(String command, Exception exception) {
} catch (IOException | InterruptedException e) {
isExecutingCommand = false;
// Handle exceptions by printing the stack trace in the terminal output
final String errorMessage = e.getMessage();
runOnUiThread(() -> {
appendTextAndScroll("Error: " + exception.getMessage() + "\n");
appendTextAndScroll("Error: " + errorMessage + "\n");
uiController(STEP_ERROR, logs);
});
}
});
}).start(); // Execute the command in a separate thread to prevent blocking the UI thread
}
@SuppressLint("SetTextI18n")
@ -585,10 +636,9 @@ public class SetupWizard2Activity extends AppCompatActivity {
if (newLog.contains("xssFjnj58Id")) {
isExecutingCommand = false;
MainSettingsManager.setStandardSetupVersion(this, AppConfig.standardSetupVersion);
MainSettingsManager.setCoreSetupVersion(this, AppConfig.coreSetupVersion);
MainSettingsManager.setsetUpWithManualSetupBefore(this, isCustomSetupMode);
uiController(STEP_JOIN_COMMUNITY);
if (ACTION == ACTION_SYSTEM_UPDATE) {
if (isSystemUpdateMode) {
uiControllerFinalSteps(STEP_FINISH);
}
} else if (newLog.contains("libproot.so --help") || newLog.contains("/bin/sh: can't fork:")) {
@ -644,6 +694,65 @@ public class SetupWizard2Activity extends AppCompatActivity {
}), getString(R.string.mirrors));
}
public static class SpinnerSelectMirrorAdapter extends BaseAdapter {
private final ArrayList<HashMap<String, String>> data;
private final LayoutInflater inflater;
private final int selectedPosition;
public SpinnerSelectMirrorAdapter(Context context, ArrayList<HashMap<String, String>> arr) {
this.data = arr;
this.inflater = LayoutInflater.from(context);
this.selectedPosition = MainSettingsManager.getSelectedMirror(context);
}
@Override
public int getCount() {
return data.size();
}
@Override
public HashMap<String, String> getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SetupWizard2Activity.SpinnerSelectMirrorAdapter.ViewHolder holder;
if (convertView == null) {
// Inflate binding only once for each new item
SimpleLayoutListViewWithCheckBinding simpleLayoutListViewWithCheckBinding =
SimpleLayoutListViewWithCheckBinding.inflate(inflater, parent, false);
// Create ViewHolder to hold binding
holder = new SetupWizard2Activity.SpinnerSelectMirrorAdapter.ViewHolder(simpleLayoutListViewWithCheckBinding);
convertView = simpleLayoutListViewWithCheckBinding.getRoot();
convertView.setTag(holder);
} else {
// Get back the saved ViewHolder
holder = (SetupWizard2Activity.SpinnerSelectMirrorAdapter.ViewHolder) convertView.getTag();
}
// Assign data
HashMap<String, String> item = data.get(position);
holder.simpleLayoutListViewWithCheckBinding.textview.setText(item.get("location"));
holder.simpleLayoutListViewWithCheckBinding.ivCheck.setVisibility(position == selectedPosition ? View.VISIBLE : View.INVISIBLE);
return convertView;
}
// ViewHolder holds binding for reuse
private record ViewHolder(SimpleLayoutListViewWithCheckBinding simpleLayoutListViewWithCheckBinding) {
}
}
public String getPath(Uri uri) {
return FileUtils.getPath(this, uri);
}

View file

@ -1,62 +0,0 @@
package com.vectras.vm.sound;
import android.content.Context;
import android.content.SharedPreferences;
public class AudioSettingsData {
Context context;
SharedPreferences sharedPreferences;
public AudioSettingsData(Context context) {
this.context = context;
sharedPreferences = context.getSharedPreferences("audio_settings", Context.MODE_PRIVATE);
}
public void setEqualizerEnabled(boolean enabled) {
sharedPreferences.edit().putBoolean("isEnabled", enabled).apply();
}
public boolean isEqualizerEnabled() {
return sharedPreferences.getBoolean("isEnabled", false);
}
public void setUpperTreble(float value) {
sharedPreferences.edit().putFloat("upperTreble", value).apply();
}
public float getUpperTreble() {
return sharedPreferences.getFloat("upperTreble", 0);
}
public void setTreble(float value) {
sharedPreferences.edit().putFloat("treble", value).apply();
}
public float getTreble() {
return sharedPreferences.getFloat("treble", 0);
}
public void setMid(float value) {
sharedPreferences.edit().putFloat("mid", value).apply();
}
public float getMid() {
return sharedPreferences.getFloat("mid", 0);
}
public void setBass(float value) {
sharedPreferences.edit().putFloat("bass", value).apply();
}
public float getBass() {
return sharedPreferences.getFloat("bass", 0);
}
public void setLowBass(float value) {
sharedPreferences.edit().putFloat("lowBass", value).apply();
}
public float getLowBass() {
return sharedPreferences.getFloat("lowBass", 0);
}
}

View file

@ -1,118 +0,0 @@
package com.vectras.vm.sound;
import android.content.Context;
import android.media.audiofx.Equalizer;
import android.util.Log;
public class SoundEffect {
final String TAG = "SoundEffect";
Context context;
public int session;
public Equalizer equalizer;
public SoundEffect(Context context, int session) {
this.context = context;
this.session = session;
equalizer = new Equalizer(1000, session);
}
public AudioFrequencyData getDeviceAudioFrequencies() {
AudioFrequencyData data = new AudioFrequencyData();
int[] targets = { 60, 230, 910, 4000, 14000 };
short bands = equalizer.getNumberOfBands();
int[] hzList = new int[bands];
for (short i = 0; i < bands; i++) {
int center = equalizer.getCenterFreq(i);
hzList[i] = center / 1000;
}
if (bands <= targets.length) {
int[] finalIds = new int[bands];
for (int i = 0; i < bands; i++) {
finalIds[i] = i;
}
data.frequencies = hzList;
data.ids = finalIds;
Log.d(TAG, "Equalizer bands: " + bands);
Log.d(TAG, "Equalizer frequencies: " + hzList[0] + ", " + hzList[1] + ", " + hzList[2] + ", " + hzList[3] + ", " + hzList[4]);
Log.d(TAG, "Equalizer ids: " + finalIds[0] + ", " + finalIds[1] + ", " + finalIds[2] + ", " + finalIds[3] + ", " + finalIds[4]);
return data;
}
int[] finalHzList = new int[5];
int[] finalIds = new int[5];
for (int i = 0; i < targets.length; i++) {
int losest = Integer.MAX_VALUE;
int bandId = 0;
for (int ii = 0; ii < hzList.length; ii++) {
if (Math.abs(targets[i] - hzList[ii]) < losest) {
losest = hzList[ii];
bandId = ii;
}
finalHzList[i] = losest;
finalIds[i] = bandId;
}
}
data.frequencies = finalHzList;
data.ids = finalIds;
Log.d(TAG, "Equalizer bands: " + bands);
Log.d(TAG, "Equalizer frequencies: " + hzList[0] + ", " + hzList[1] + ", " + hzList[2] + ", " + hzList[3] + ", " + hzList[4]);
Log.d(TAG, "Equalizer ids: " + finalIds[0] + ", " + finalIds[1] + ", " + finalIds[2] + ", " + finalIds[3] + ", " + finalIds[4]);
return data;
}
public void applyEffect(float[] dBData) {
short bands = equalizer.getNumberOfBands();
if (bands < 2) {
Log.d(TAG, "Equalizer bands: " + bands);
return;
}
AudioFrequencyData data = getDeviceAudioFrequencies();
equalizer.setBandLevel((short) data.ids[0], (short) dBData[0]);
equalizer.setBandLevel((short) data.ids[1], (short) dBData[1]);
if (bands > 2) equalizer.setBandLevel((short) data.ids[2], (short) dBData[2]);
if (bands > 3) equalizer.setBandLevel((short) data.ids[3], (short) dBData[3]);
if (bands > 4) equalizer.setBandLevel((short) data.ids[4], (short) dBData[4]);
Log.d(TAG, "Equalizer dB: " + dBData[0] + ", " + dBData[1] + ", " + dBData[2] + ", " + dBData[3] + ", " + dBData[4]);
}
public void release() {
if (equalizer != null) {
equalizer.release();
}
}
public void setEnabled(boolean isEnabled) {
equalizer.setEnabled(isEnabled);
}
public short getMinBandLevelRange() {
return equalizer.getBandLevelRange()[0];
}
public short getMaxBandLevelRange() {
return equalizer.getBandLevelRange()[1];
}
public static class AudioFrequencyData {
int[] frequencies;
int[] ids;
}
}

View file

@ -22,13 +22,11 @@ import com.anbui.elephant.interaction.Interaction;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.ImagePrvActivity;
import com.vectras.vm.R;
import com.vectras.vm.VMManager;
import com.vectras.vm.creator.VMCreatorActivity;
import com.vectras.vm.databinding.ActivityRomInfoBinding;
import com.vectras.vm.file.FilePickerDialog;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.ImageUtils;
@ -74,90 +72,89 @@ public class RomInfo extends AppCompatActivity {
}
private final ActivityResultLauncher<String> romPicker =
registerForActivityResult(new ActivityResultContracts.GetContent(), this::handlePickedRom);
registerForActivityResult(new ActivityResultContracts.GetContent(), uri -> {
public void handlePickedRom(Uri uri) {
if (uri == null) return;
if (uri == null) return;
executor.execute(() -> {
String filePath;
try {
File selectedFilePath = new File(getPath(uri));
filePath = selectedFilePath.getPath();
} catch (Exception e) {
filePath = "";
}
String selectedFileName = FileUtils.getFileNameFromUri(this, uri);
if (isFinishing() || isDestroyed()) return;
String finalFilePath = filePath;
runOnUiThread(() -> {
if (selectedFileName.equals(getIntent().getStringExtra("filename")) ||
(selectedFileName.endsWith(".cvbi.zip") && selectedFileName.equals(getIntent().getStringExtra("filename") + ".zip"))) {
Intent intent = new Intent();
if (getIntent().hasExtra("icon") &&
!Objects.requireNonNull(getIntent().getStringExtra("icon")).isEmpty() &&
(!selectedFileName.endsWith(".cvbi")
|| !selectedFileName.endsWith(".cvbi.zip"))) {
Glide.with(this)
.asBitmap()
.load(getIntent().getStringExtra("icon"))
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource,
@Nullable Transition<? super Bitmap> transition) {
File cacheDir = getExternalCacheDir();
if (cacheDir != null)
ImageUtils.saveBitmapToPNGFile(resource, cacheDir.getAbsolutePath(), "thumbnail.png");
intent.putExtra("romicon", cacheDir != null ? cacheDir.getAbsolutePath() + "/thumbnail.png" : "");
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
intent.putExtra("romicon", "");
}
});
} else {
intent.putExtra("romicon", "");
executor.execute(() -> {
String filePath;
try {
File selectedFilePath = new File(getPath(uri));
filePath = selectedFilePath.getPath();
} catch (Exception e) {
filePath = "";
}
intent.setClass(getApplicationContext(), VMCreatorActivity.class);
intent.putExtra("addromnow", "");
intent.putExtra("romname", getIntent().getStringExtra("title"));
intent.putExtra("romfilename", getIntent().getStringExtra("filename"));
intent.putExtra("finalromfilename", getIntent().getStringExtra("finalromfilename"));
intent.putExtra("rompath", finalFilePath);
intent.putExtra("romuri", uri.toString());
if (Objects.requireNonNull(getIntent().getStringExtra("extra")).contains(selectedFileName)) {
intent.putExtra("addtodrive", "");
intent.putExtra("romextra", getIntent().getStringExtra("extra"));
} else {
intent.putExtra("addtodrive", "1");
intent.putExtra("romextra", getIntent().getStringExtra("extra"));
}
String selectedFileName = FileUtils.getFileNameFromUri(this, uri);
VMManager.setArch(getIntent().hasExtra("arch") && getIntent().getStringExtra("arch") != null ? Objects.requireNonNull(getIntent().getStringExtra("arch")) : "", this);
if (isFinishing() || isDestroyed()) return;
startActivity(intent);
} else {
DialogUtils.oneDialog(RomInfo.this,
getString(R.string.problem_has_been_detected),
getString(R.string.please_select) + " " + getIntent().getStringExtra("filename"),
getString(R.string.ok),
true, R.drawable.warning_48px,
true,
null,
null);
}
String finalFilePath = filePath;
runOnUiThread(() -> {
if (selectedFileName.equals(getIntent().getStringExtra("filename")) ||
(selectedFileName.endsWith(".cvbi.zip") && selectedFileName.equals(getIntent().getStringExtra("filename") + ".zip"))) {
Intent intent = new Intent();
if (getIntent().hasExtra("icon") &&
!Objects.requireNonNull(getIntent().getStringExtra("icon")).isEmpty() &&
(!selectedFileName.endsWith(".cvbi")
|| !selectedFileName.endsWith(".cvbi.zip"))) {
Glide.with(this)
.asBitmap()
.load(getIntent().getStringExtra("icon"))
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource,
@Nullable Transition<? super Bitmap> transition) {
File cacheDir = getExternalCacheDir();
if (cacheDir != null)
ImageUtils.saveBitmapToPNGFile(resource, cacheDir.getAbsolutePath(), "thumbnail.png");
intent.putExtra("romicon", cacheDir != null ? cacheDir.getAbsolutePath() + "/thumbnail.png" : "");
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
intent.putExtra("romicon", "");
}
});
} else {
intent.putExtra("romicon", "");
}
intent.setClass(getApplicationContext(), VMCreatorActivity.class);
intent.putExtra("addromnow", "");
intent.putExtra("romname", getIntent().getStringExtra("title"));
intent.putExtra("romfilename", getIntent().getStringExtra("filename"));
intent.putExtra("finalromfilename", getIntent().getStringExtra("finalromfilename"));
intent.putExtra("rompath", finalFilePath);
intent.putExtra("romuri", uri.toString());
if (Objects.requireNonNull(getIntent().getStringExtra("extra")).contains(selectedFileName)) {
intent.putExtra("addtodrive", "");
intent.putExtra("romextra", getIntent().getStringExtra("extra"));
} else {
intent.putExtra("addtodrive", "1");
intent.putExtra("romextra", getIntent().getStringExtra("extra"));
}
VMManager.setArch(getIntent().hasExtra("arch") && getIntent().getStringExtra("arch") != null ? Objects.requireNonNull(getIntent().getStringExtra("arch")) : "", this);
startActivity(intent);
} else {
DialogUtils.oneDialog(RomInfo.this,
getString(R.string.problem_has_been_detected),
getString(R.string.please_select) + " " + getIntent().getStringExtra("filename"),
getString(R.string.ok),
true, R.drawable.warning_48px,
true,
null,
null);
}
});
});
});
});
}
public String getPath(Uri uri) {
return FileUtils.getPath(RomInfo.this, uri);
@ -171,12 +168,7 @@ public class RomInfo extends AppCompatActivity {
if (getIntent().hasExtra("isRomInfo") && getIntent().getBooleanExtra("isRomInfo", false)) {
binding.btnPick.setOnClickListener(v -> {
try {
if (MainSettingsManager.getBuiltInFilePicker(this)) {
FilePickerDialog filePickerDialog = new FilePickerDialog();
filePickerDialog.pick(this, filePickerDialog.ROM_FILE, (path -> handlePickedRom(Uri.fromFile(new File(path)))));
} else {
romPicker.launch("*/*");
}
romPicker.launch("*/*");
} catch (Exception e) {
IntentUtils.showErrorDialog(this);
}

View file

@ -11,14 +11,10 @@ import com.vectras.vm.R;
public class ClipboardUltils {
public static void copyToClipboard(Context context, String text) {
copyToClipboard(context, text, true);
}
public static void copyToClipboard(Context context, String text, boolean showToast) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("From Vectras VM", text);
assert clipboard != null;
clipboard.setPrimaryClip(clip);
if (showToast) Toast.makeText(context, context.getString(R.string.copied), Toast.LENGTH_SHORT).show();
Toast.makeText(context, context.getString(R.string.copied), Toast.LENGTH_SHORT).show();
}
}

View file

@ -1,11 +1,9 @@
package com.vectras.vm.utils;
import android.app.Activity;
import android.content.Context;
import com.vectras.vm.VectrasApp;
import com.vectras.vterm.Terminal;
import com.vectras.vterm.Terminal2;
public class CommandUtils {
public static String createForSelectedMirror(boolean _https, String _url, String _beforemain) {
@ -20,23 +18,24 @@ public class CommandUtils {
}
public static void run(String _command, boolean _isShowResult, Activity _activity) {
new Terminal2(_activity).execute(_command);
Terminal vterm = new Terminal(_activity);
vterm.executeShellCommand2(_command, _isShowResult, _activity);
}
public static String getQemuVersionName(Context context) {
String qemuVersion = getQemuVersion(context);
public static String getQemuVersionName() {
String qemuVersion = getQemuVersion();
if (qemuVersion.toLowerCase().contains("failed") || qemuVersion.toLowerCase().contains("not found"))
return "";
return (qemuVersion.contains("Error") ? qemuVersion.substring(0, qemuVersion.indexOf("Error")) : qemuVersion) + (is3dfxVersion(context) ? " - 3dfx" : "");
return (qemuVersion.contains("Error") ? qemuVersion.substring(0, qemuVersion.indexOf("Error")) : qemuVersion) + (is3dfxVersion() ? " - 3dfx" : "");
}
public static String getQemuVersion(Context context) {
return VectrasApp.getContext() == null ? "Unknow" : new Terminal2(context).executeOnThisThread("qemu-system-x86_64 --version | head -n1 | awk '{print $4}'").replaceAll("\n", "");
public static String getQemuVersion() {
return VectrasApp.getContext() == null ? "Unknow" : Terminal.executeShellCommandWithResult("qemu-system-x86_64 --version | head -n1 | awk '{print $4}'", VectrasApp.getContext()).replaceAll("\n", "");
}
public static boolean is3dfxVersion(Context context) {
return VectrasApp.getContext() != null && new Terminal2(context).executeOnThisThread("qemu-system-x86_64 --version").contains("3dfx");
public static boolean is3dfxVersion() {
return VectrasApp.getContext() != null && Terminal.executeShellCommandWithResult("qemu-system-x86_64 --version", VectrasApp.getContext()).contains("3dfx");
}
}

View file

@ -70,13 +70,7 @@ public class DeviceUtils {
}
public static boolean is64bit() {
try {
return new CpuHelper().is64Bit();
} catch (UnsatisfiedLinkError e) {
return Build.SUPPORTED_ABIS[0].contains("64") &&
Build.SUPPORTED_64_BIT_ABIS != null &&
Build.SUPPORTED_64_BIT_ABIS.length > 0;
}
return new CpuHelper().is64Bit();
}
public static boolean isArm() {
return Build.SUPPORTED_ABIS[0].contains("arm");

View file

@ -1,13 +0,0 @@
package com.vectras.vm.utils;
import android.content.Context;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
public class GmsChecker {
public static boolean isAvailable(Context context) {
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
return googleApiAvailability.isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
}
}

View file

@ -1,7 +1,5 @@
package com.vectras.vm.utils;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
@ -16,14 +14,11 @@ import java.util.HashMap;
import java.util.Objects;
public class JSONUtils {
private static final String TAG = "JSONUtils";
public static boolean isValidFromString(String _content) {
try {
JsonElement element = JsonParser.parseString(_content);
return element != null;
} catch (Exception e) {
Log.e(TAG, "isValidFromString: " + e.getMessage());
return false;
}
}

View file

@ -2,16 +2,14 @@ package com.vectras.vm.utils;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import androidx.appcompat.app.AlertDialog;
import com.vectras.vm.AppConfig;
import com.vectras.vm.R;
import com.vectras.vterm.Terminal;
import com.vectras.vterm.Terminal2;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@ -68,69 +66,30 @@ public class LibraryChecker {
() -> {
// Create the installation command
String installCommand = "apk add " + missingLibraries.replace("\n", " ");
Terminal2 terminal2 = new Terminal2(context);
terminal2.setShowProgressDialog(true);
terminal2.execute(installCommand, new Terminal2.Terminal2Callback() {
@Override
public void onRunning(String command, String newLine) {
// Nothing to do.
}
@Override
public void onFinished(String command, String log, int status) {
new Handler(Looper.getMainLooper()).post(() -> {
if (status == terminal2.SUCCESS) {
DialogUtils.oneDialog(
activity,
activity.getString(R.string.done),
activity.getString(R.string.the_necessary_packages_have_been_installed),
R.drawable.check_24px
);
} else {
DialogUtils.oopsDialog(context, log);
}
});
}
@Override
public void onError(String command, Exception exception) {
new Handler(Looper.getMainLooper()).post(() -> DialogUtils.oopsDialog(context, exception.getMessage()));
}
});
new Terminal(context).executeShellCommand(installCommand, true, true, activity);
},
null,
null
);
}
// Method to show the "All Libraries Installed" dialog
private void showAllLibrariesInstalledDialog(Activity activity) {
new AlertDialog.Builder(activity, R.style.MainDialogTheme)
.setTitle("All Libraries Installed")
.setMessage("All required libraries are already installed.")
.setPositiveButton("OK", (dialog, which) -> dialog.dismiss())
.show();
}
// Method to check if the package is installed
public void isPackageInstalled(String packageName, Terminal.CommandCallback callback) {
String command = "apk info";
Terminal2 terminal2 = new Terminal2(context);
terminal2.execute(command, new Terminal2.Terminal2Callback() {
@Override
public void onRunning(String command, String newLine) {
// Nothing to do.
}
@Override
public void onFinished(String command, String log, int status) {
new Handler(Looper.getMainLooper()).post(() -> {
if (callback != null) {
if (status == terminal2.SUCCESS) {
callback.onCommandCompleted(log, "");
} else {
callback.onCommandCompleted(log, log);
}
}
});
}
@Override
public void onError(String command, Exception exception) {
new Handler(Looper.getMainLooper()).post(() -> callback.onCommandCompleted("", exception.getMessage()));
Terminal terminal = new Terminal(context);
terminal.executeShellCommand(command, (Activity) context, false, (output, errors) -> {
if (callback != null) {
callback.onCommandCompleted(output, errors);
}
});
}
@ -139,30 +98,59 @@ public class LibraryChecker {
public static void isPackageInstalled2(Context context, String packageName, Terminal.CommandCallback callback) {
String command = "apk info";
Terminal2 terminal2 = new Terminal2(context);
terminal2.execute(command, new Terminal2.Terminal2Callback() {
@Override
public void onRunning(String command, String newLine) {
// Nothing to do.
}
@Override
public void onFinished(String command, String log, int status) {
new Handler(Looper.getMainLooper()).post(() -> {
if (callback != null) {
if (status == terminal2.SUCCESS) {
callback.onCommandCompleted(log, "");
} else {
callback.onCommandCompleted(log, log);
}
}
});
}
@Override
public void onError(String command, Exception exception) {
new Handler(Looper.getMainLooper()).post(() -> callback.onCommandCompleted("", exception.getMessage()));
Terminal terminal = new Terminal(context);
terminal.executeShellCommand(command, context, false, (output, errors) -> {
if (callback != null) {
callback.onCommandCompleted(output, errors);
}
});
}
public void checkAndInstallXFCE4(Activity activity) {
// XFCE4 meta-package
String xfce4Package = "xfce4";
// Check if XFCE4 is installed
isPackageInstalled(xfce4Package, (output, errors) -> {
boolean isInstalled = false;
// Check if the package exists in the installed packages output
if (output != null) {
Set<String> installedPackages = new HashSet<>();
for (String installedPackage : output.split("\n")) {
installedPackages.add(installedPackage.trim());
}
isInstalled = installedPackages.contains(xfce4Package.trim());
}
// If not installed, show a dialog to install it
if (!isInstalled) {
showInstallDialog(activity, xfce4Package);
} else {
showAlreadyInstalledDialog(activity);
}
});
}
private void showInstallDialog(Activity activity, String packageName) {
new AlertDialog.Builder(activity, R.style.MainDialogTheme)
.setTitle("Install XFCE4")
.setMessage("XFCE4 is not installed. Would you like to install it?")
.setCancelable(false)
.setPositiveButton("Install", (dialog, which) -> {
String installCommand = "apk add " + packageName;
new Terminal(context).executeShellCommand(installCommand, true, true, activity);
})
.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss())
.show();
}
private void showAlreadyInstalledDialog(Activity activity) {
new AlertDialog.Builder(activity, R.style.MainDialogTheme)
.setTitle("XFCE4 Installed")
.setMessage("XFCE4 is already installed on this system.")
.setPositiveButton("OK", (dialog, which) -> dialog.dismiss())
.show();
}
}

View file

@ -1,4 +1,4 @@
package com.vectras.vm.sound;
package com.vectras.vm.utils;
import android.app.Activity;
import android.content.Context;
@ -7,8 +7,6 @@ import android.media.AudioFormat;
import android.media.AudioTrack;
import android.util.Log;
import com.vectras.vm.utils.FileUtils;
import java.io.RandomAccessFile;
public class StreamAudio {
@ -19,8 +17,6 @@ public class StreamAudio {
private int sampleRate = 48000;
public boolean isDestroyed;
private StreamAudio cross;
AudioTrack audioTrack;
private SoundEffect soundEffect;
public StreamAudio(Context context) {
this.context = context;
@ -31,7 +27,6 @@ public class StreamAudio {
}
public void stop() {
if (audioTrack != null) audioTrack.stop();
isPlay = false;
}
@ -59,28 +54,6 @@ public class StreamAudio {
sampleRate = 48000;
}
float volume = 1f;
public void setVolume(float volume) {
this.volume = volume / 100;
if (audioTrack != null) audioTrack.setVolume(this.volume);
}
float nextPlayVolume = -1;
public void setNextPlayVolume(float volume) {
this.volume = volume / 100;
}
public float getVolume() {
return volume * 100;
}
public void release() {
isPlay = false;
releaseSoundEffect();
}
public void streamFromFile() {
if (isPlay) return;
@ -114,7 +87,7 @@ public class StreamAudio {
return;
}
audioTrack = new AudioTrack.Builder()
AudioTrack audioTrack = new AudioTrack.Builder()
.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.build())
@ -127,12 +100,6 @@ public class StreamAudio {
.setTransferMode(AudioTrack.MODE_STREAM)
.build();
audioTrack.setVolume(nextPlayVolume < 0 ? volume : nextPlayVolume);
nextPlayVolume = -1;
applyEffect(audioTrack);
audioTrack.play();
if (cross != null && !cross.isDestroyed && cross.isPlaying()) cross.stop();
@ -166,63 +133,6 @@ public class StreamAudio {
}).start();
}
float[] currentdBData = new float[5];
public void applyEffect(AudioTrack audioTrack) {
if (soundEffect != null && soundEffect.equalizer.getNumberOfBands() < 2) return;
AudioSettingsData audioSettingsData = new AudioSettingsData(context);
if (!audioSettingsData.isEqualizerEnabled()) {
releaseSoundEffect();
return;
}
if (soundEffect == null || soundEffect.session != audioTrack.getAudioSessionId())
soundEffect = new SoundEffect(context, audioTrack.getAudioSessionId());
if (soundEffect.equalizer.getNumberOfBands() < 2) return;
float[] dBData = new float[5];
//Bass -> Mid -> Treble
dBData[0] = audioSettingsData.getLowBass();
dBData[1] = audioSettingsData.getBass();
dBData[2] = audioSettingsData.getMid();
dBData[3] = audioSettingsData.getTreble();
dBData[4] = audioSettingsData.getUpperTreble();
if (
currentdBData[0] == dBData[0] &&
currentdBData[1] == dBData[1] &&
currentdBData[2] == dBData[2] &&
currentdBData[3] == dBData[3] &&
currentdBData[4] == dBData[4]) {
return;
}
this.currentdBData = dBData;
// Convert dB to mB
for (int i = 0; i < dBData.length; i++) {
dBData[i] = dBData[i] * 100;
}
soundEffect.applyEffect(dBData);
soundEffect.setEnabled(audioSettingsData.isEqualizerEnabled());
Log.d(TAG, "Equalizer enabled: " + audioSettingsData.isEqualizerEnabled());
}
public void releaseSoundEffect() {
if (soundEffect != null) {
soundEffect.setEnabled(false);
soundEffect.release();
soundEffect = null;
}
}
private boolean isContextDestroyed(Context context) {
if (context instanceof Activity activity) {
isDestroyed = activity.isDestroyed() || activity.isFinishing();

View file

@ -49,7 +49,7 @@ public class CheckBoxView extends LinearLayout {
typedArray.recycle();
}
setOnClickListener(v -> checkBox.setChecked(!checkBox.isChecked()));
findViewById(R.id.root).setOnClickListener(v -> checkBox.setChecked(!checkBox.isChecked()));
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (listener != null) {

View file

@ -23,8 +23,6 @@ public class DynamicBubble {
}
private void setup() {
bubble.animate().alpha(0.5f).setDuration(200);
bubble.setOnTouchListener((v, event) -> {
switch (event.getActionMasked()) {
@ -46,9 +44,6 @@ public class DynamicBubble {
// If the displacement exceeds the threshold, it is determined that pulling is occurring.
if (Math.abs(movedX) > CLICK_ACTION_THRESHOLD || Math.abs(movedY) > CLICK_ACTION_THRESHOLD) {
if (!isDragging) bubble.animate().alpha(1).setDuration(200);
isDragging = true;
// Move the view using your finger.
@ -80,8 +75,6 @@ public class DynamicBubble {
}
private void onDropped() {
bubble.animate().alpha(0.5f).setDuration(200);
if (bubble.getX() > (float) container.getWidth() / 2) {
bubble.animate().x(container.getWidth() - bubble.getWidth());
} else {

View file

@ -52,7 +52,7 @@ public class SwitchView extends LinearLayout {
typedArray.recycle();
}
setOnClickListener(v -> switchWidget.setChecked(!switchWidget.isChecked()));
findViewById(R.id.root).setOnClickListener(v -> switchWidget.setChecked(!switchWidget.isChecked()));
switchWidget.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (listener != null) {

View file

@ -2,6 +2,8 @@ package com.vectras.vm.x11;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import android.app.Dialog;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT;
@ -14,6 +16,8 @@ import static android.view.InputDevice.KEYBOARD_TYPE_ALPHABETIC;
import static android.view.KeyEvent.*;
import static android.view.WindowManager.LayoutParams.*;
import android.view.WindowManager;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.fragment.app.FragmentTransaction;
@ -33,7 +37,7 @@ import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.manager.VmListManager;
import com.vectras.vm.manager.VmPicker;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.sound.StreamAudio;
import com.vectras.vm.utils.StreamAudio;
import com.vectras.vm.utils.UIUtils;
import static com.vectras.vm.x11.CmdEntryPoint.ACTION_START;
@ -76,6 +80,7 @@ import android.view.Window;
import android.view.WindowInsets;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
@ -93,6 +98,7 @@ import com.vectras.vm.x11.utils.KeyInterceptor;
import com.vectras.vm.x11.utils.TermuxX11ExtraKeys;
import com.vectras.vm.x11.utils.X11ToolbarViewPager;
import com.vectras.vm.R;
import com.vectras.vterm.Terminal;
import java.util.ArrayList;
import java.util.HashMap;
@ -752,7 +758,7 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
@Override
protected void onDestroy() {
unregisterReceiver(receiver);
if (streamAudio != null) streamAudio.release();
if (streamAudio != null) streamAudio.stop();
super.onDestroy();
}

View file

@ -1,252 +0,0 @@
package com.vectras.vterm;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.vectras.vm.AppConfig;
import com.vectras.vm.R;
import com.vectras.vm.logger.VectrasStatus;
import com.vectras.vm.utils.FileUtils;
import com.vectras.vm.utils.ProgressDialog;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class Terminal2 {
final String TAG = "Terminal2";
public final int SUCCESS = 0;
public final int ERROR = 1;
Context context;
String user = "root";
String home = "/root";
String display = ":0";
String shell = "/bin/sh";
String startup = "";
String logs = "";
String lastLog = "";
boolean isShowProgressDialog;
ProgressDialog progressDialog = null;
public interface Terminal2Callback {
void onRunning(String command, String newLine);
void onFinished(String command, String log, int status);
void onError(String command, Exception exception);
}
public Terminal2(Context context) {
this.context = context;
}
public void setUserName(String user) {
this.user = user;
home = user.equals("root") ? "/root" : "/home/" + user;
}
public void setRootMode() {
this.user = "root";
home = "/root";
}
public void setDefaultShell() {
this.shell = "/bin/sh";
}
public void setDefaultShellBash() {
this.shell = "/bin/bash";
}
public void setStartup(String command) {
this.startup = command;
}
public String getLogs() {
return logs;
}
public void clearLog() {
logs = "";
}
public void setShowProgressDialog(boolean isShow) {
this.isShowProgressDialog = isShow;
}
public String executeOnThisThread(String command) {
execute(command, null, false);
return lastLog;
}
public void execute(String command) {
execute(command, null);
}
public void execute(String command, Terminal2Callback callback) {
execute(command, callback, true);
}
public void execute(String command, Terminal2Callback callback, boolean isNewThread) {
AtomicReference<Process> process = new AtomicReference<>();
Runnable runnable = () -> {
if (isShowProgressDialog) {
progressDialog = new ProgressDialog(context);
progressDialog.setText(context.getString(R.string.executing_command_please_wait));
new Handler(Looper.getMainLooper()).post((progressDialog::show));
}
try {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.redirectErrorStream(true);
String filesDir = Objects.requireNonNull(context.getFilesDir().getAbsolutePath());
String prootPath = new File(filesDir, "usr/bin/proot").getAbsolutePath();
String tmpDir = new File(filesDir, "usr/tmp").getAbsolutePath();
if (!FileUtils.isFileExists(filesDir + "/distro" + shell)) {
setDefaultShell();
}
if (!FileUtils.isFileExists(filesDir + "/distro" + home)) {
FileUtils.createDirectory(filesDir + "/distro" + home);
}
processBuilder.environment().put("PROOT_TMP_DIR", tmpDir);
processBuilder.environment().put("HOME", home);
processBuilder.environment().put("USER", user);
processBuilder.environment().put("TERM", "xterm-256color");
processBuilder.environment().put("TMPDIR", "/tmp");
processBuilder.environment().put("SHELL", shell);
processBuilder.environment().put("DISPLAY", display);
processBuilder.environment().put("XDG_RUNTIME_DIR", "/tmp");
processBuilder.environment().put("SDL_VIDEODRIVER", "x11");
String[] prootCommand = {
prootPath,
"--kill-on-exit",
"--link2symlink",
"-0",
"-r", filesDir + "/distro",
"-b", "/dev",
"-b", "/proc",
"-b", "/sys",
"-b", AppConfig.internalDataDirPath + "distro" + home + ":/dev/shm",
"-b", "/sdcard",
"-b", "/storage",
"-b", "/data",
"-b", AppConfig.internalDataDirPath + "usr/tmp:/tmp",
"-w", home,
shell,
"--login"
};
processBuilder.command(prootCommand);
process.set(processBuilder.start());
resultData data = startProcess((startup.isEmpty() ? "" : startup + " && ") + command, process.get(), callback);
if (callback != null) callback.onFinished(command, data.log.toString(), data.status);
} catch (Exception e) {
if (callback != null) callback.onError(command, e);
addToLogs(command, e.getMessage());
} finally {
if (progressDialog != null) {
new Handler(Looper.getMainLooper()).post(() -> {
progressDialog.reset();
progressDialog = null;
});
}
}
};
if (isNewThread) {
new Thread(runnable).start();
} else {
runnable.run();
}
}
private resultData startProcess(String command, Process process, Terminal2Callback callback) {
resultData data = new resultData();
AtomicInteger exitCode = new AtomicInteger();
int MAX_LOG_SIZE = 200_000; // ~200KB text
StringBuilder output = new StringBuilder();
try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
writer.write(command);
writer.newLine();
writer.flush();
writer.close();
String line;
while ((line = reader.readLine()) != null) {
Log.d(TAG, line);
VectrasStatus.logError(line);
output.append(line).append("\n");
if (callback != null) callback.onRunning(command, line);
if (output.length() > MAX_LOG_SIZE) {
output.delete(0, output.length() - MAX_LOG_SIZE);
}
if (progressDialog != null) {
String finalLine = line;
new Handler(Looper.getMainLooper()).post(() -> progressDialog.setText(finalLine));
}
}
try {
exitCode.set(process.waitFor());
} catch (InterruptedException e) {
exitCode.set(ERROR);
}
data.status = exitCode.get();
reader.close();
} catch (Exception e) {
output.append(e.getMessage());
Log.e(TAG, "streamLog: ", e);
}
data.status = exitCode.get();
data.log = output;
addToLogs(command, output.toString());
return data;
}
private void addToLogs(String command,String log) {
lastLog = log;
if (!logs.isEmpty()) {
logs += "\n\n----------\n\n";
}
logs += "$ " + command + "\n\n";
logs += log;
if (logs.contains("\n") && logs.lastIndexOf("\n") > 1000)
logs = logs.substring(logs.lastIndexOf("\n") + 1);
}
private class resultData {
StringBuilder log;
int status;
}
}

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M40,720Q50,615 104,529Q158,443 243,389L166,260Q157,246 161.5,230Q166,214 180,206Q194,197 210,201Q226,205 234,219L314,352Q352,336 393.5,328Q435,320 480,320Q525,320 566.5,328Q608,336 646,352L726,219Q734,205 750,201Q766,197 780,206Q794,214 798,230Q802,246 794,260L717,389Q802,443 856,529Q910,615 920,720L40,720ZM720.5,568.5Q722,551 711,534Q700,517 684,512Q668,507 655,516Q642,525 640,542Q638,559 649,576Q660,593 676.5,598.5Q693,604 706,595Q719,586 720.5,568.5ZM284,598Q300,593 311,576Q322,559 320.5,541.5Q319,524 306,515Q293,506 276.5,511.5Q260,517 249,534Q238,551 240,568Q242,585 255,594Q268,603 284,598Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M440,720L440,352L296,496L240,440L480,200L720,440L664,496L520,352L520,720L440,720Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M480,932L346,800L160,800L160,614L28,480L160,346L160,160L346,160L480,28L614,160L800,160L800,346L932,480L800,614L800,800L614,800L480,932ZM621.5,621.5Q680,563 680,480Q680,397 621.5,338.5Q563,280 480,280Q397,280 338.5,338.5Q280,397 280,480Q280,563 338.5,621.5Q397,680 480,680Q563,680 621.5,621.5ZM395,565Q360,530 360,480Q360,430 395,395Q430,360 480,360Q530,360 565,395Q600,430 600,480Q600,530 565,565Q530,600 480,600Q430,600 395,565ZM480,820L580,720L720,720L720,580L820,480L720,380L720,240L580,240L480,140L380,240L240,240L240,380L140,480L240,580L240,720L380,720L480,820ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M320,720L80,480L320,240L377,297L193,481L376,664L320,720ZM640,720L583,663L767,479L584,296L640,240L880,480L640,720Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M480,840Q329,840 224.5,793.5Q120,747 120,680L120,280Q120,214 225.5,167Q331,120 480,120Q629,120 734.5,167Q840,214 840,280L840,680Q840,747 735.5,793.5Q631,840 480,840ZM480,361Q569,361 659,335.5Q749,310 760,281Q749,252 659.5,226Q570,200 480,200Q389,200 301.5,225.5Q214,251 200,281Q214,311 301.5,336Q389,361 480,361ZM480,560Q522,560 561,556Q600,552 635.5,544.5Q671,537 702.5,526Q734,515 760,501L760,381Q734,395 702.5,406Q671,417 635.5,424.5Q600,432 561,436Q522,440 480,440Q438,440 398,436Q358,432 322.5,424.5Q287,417 256,406Q225,395 200,381L200,501Q225,515 256,526Q287,537 322.5,544.5Q358,552 398,556Q438,560 480,560ZM480,760Q526,760 573.5,753Q621,746 661,734.5Q701,723 728,708.5Q755,694 760,679L760,581Q734,595 702.5,606Q671,617 635.5,624.5Q600,632 561,636Q522,640 480,640Q438,640 398,636Q358,632 322.5,624.5Q287,617 256,606Q225,595 200,581L200,680Q205,695 231.5,709Q258,723 298,734.5Q338,746 386,753Q434,760 480,760Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M320,720L640,720L640,640L320,640L320,720ZM320,560L640,560L640,480L320,480L320,560ZM240,880Q207,880 183.5,856.5Q160,833 160,800L160,160Q160,127 183.5,103.5Q207,80 240,80L560,80L800,320L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM520,360L520,160L240,160Q240,160 240,160Q240,160 240,160L240,800Q240,800 240,800Q240,800 240,800L720,800Q720,800 720,800Q720,800 720,800L720,360L520,360ZM240,160L240,160L240,360L240,360L240,160L240,360L240,360L240,800Q240,800 240,800Q240,800 240,800L240,800Q240,800 240,800Q240,800 240,800L240,160Q240,160 240,160Q240,160 240,160Z"/>
</vector>

View file

@ -1,11 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M240,880Q207,880 183.5,856.5Q160,833 160,800L160,160Q160,127 183.5,103.5Q207,80 240,80L560,80L800,320L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM520,360L520,160L240,160Q240,160 240,160Q240,160 240,160L240,800Q240,800 240,800Q240,800 240,800L720,800Q720,800 720,800Q720,800 720,800L720,360L520,360ZM240,160L240,160L240,360L240,360L240,160L240,360L240,360L240,800Q240,800 240,800Q240,800 240,800L240,800Q240,800 240,800Q240,800 240,800L240,160Q240,160 240,160Q240,160 240,160Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M640,480L640,400L720,400L720,480L640,480ZM640,560L560,560L560,480L640,480L640,560ZM640,640L640,560L720,560L720,640L640,640ZM447,320L367,240L160,240Q160,240 160,240Q160,240 160,240L160,720Q160,720 160,720Q160,720 160,720L560,720L560,640L640,640L640,720L800,720Q800,720 800,720Q800,720 800,720L800,320Q800,320 800,320Q800,320 800,320L640,320L640,400L560,400L560,320L447,320ZM160,800Q127,800 103.5,776.5Q80,753 80,720L80,240Q80,207 103.5,183.5Q127,160 160,160L400,160L480,240L800,240Q833,240 856.5,263.5Q880,287 880,320L880,720Q880,753 856.5,776.5Q833,800 800,800L160,800ZM160,720L160,720Q160,720 160,720Q160,720 160,720L160,320Q160,320 160,320Q160,320 160,320L160,320L160,240L160,240Q160,240 160,240Q160,240 160,240L160,720Q160,720 160,720Q160,720 160,720Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M280,720L280,240L360,240L360,720L280,720ZM440,880L440,80L520,80L520,880L440,880ZM120,560L120,400L200,400L200,560L120,560ZM600,720L600,240L680,240L680,720L600,720ZM760,560L760,400L840,400L840,560L760,560Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="96dp"
android:height="96dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M791,905L520,634L520,880L440,880L440,554L360,474L360,720L280,720L280,394L55,169L112,112L848,848L791,905ZM120,560L120,400L200,400L200,560L120,560ZM520,406L440,326L440,80L520,80L520,406ZM680,566L600,486L600,240L680,240L680,566ZM760,560L760,400L840,400L840,560L760,560Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M200,840Q167,840 143.5,816.5Q120,793 120,760L120,200Q120,167 143.5,143.5Q167,120 200,120L760,120Q793,120 816.5,143.5Q840,167 840,200L840,760Q840,793 816.5,816.5Q793,840 760,840L200,840ZM200,760L760,760Q760,760 760,760Q760,760 760,760L760,200Q760,200 760,200Q760,200 760,200L200,200Q200,200 200,200Q200,200 200,200L200,760Q200,760 200,760Q200,760 200,760ZM240,680L720,680L570,480L450,640L360,520L240,680ZM200,760Q200,760 200,760Q200,760 200,760L200,200Q200,200 200,200Q200,200 200,200L200,200Q200,200 200,200Q200,200 200,200L200,760Q200,760 200,760Q200,760 200,760Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M160,360L160,280L240,280L240,360L160,360ZM160,680L160,440L240,440L240,680L160,680ZM440,680L360,680Q327,680 303.5,656.5Q280,633 280,600L280,360Q280,327 303.5,303.5Q327,280 360,280L440,280Q473,280 496.5,303.5Q520,327 520,360L520,600Q520,633 496.5,656.5Q473,680 440,680ZM360,600L440,600Q440,600 440,600Q440,600 440,600L440,360Q440,360 440,360Q440,360 440,360L360,360Q360,360 360,360Q360,360 360,360L360,600Q360,600 360,600Q360,600 360,600ZM560,680L560,600L720,600Q720,600 720,600Q720,600 720,600L720,520Q720,520 720,520Q720,520 720,520L640,520Q607,520 583.5,496.5Q560,473 560,440L560,360Q560,327 583.5,303.5Q607,280 640,280L800,280L800,360L640,360Q640,360 640,360Q640,360 640,360L640,440Q640,440 640,440Q640,440 640,440L720,440Q753,440 776.5,463.5Q800,487 800,520L800,600Q800,633 776.5,656.5Q753,680 720,680L560,680Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M223.5,536.5Q200,513 200,480Q200,447 223.5,423.5Q247,400 280,400Q313,400 336.5,423.5Q360,447 360,480Q360,513 336.5,536.5Q313,560 280,560Q247,560 223.5,536.5ZM280,720Q180,720 110,650Q40,580 40,480Q40,380 110,310Q180,240 280,240Q347,240 401.5,273Q456,306 488,360L840,360L960,480L780,660L700,600L620,660L535,600L488,600Q456,654 401.5,687Q347,720 280,720ZM280,640Q336,640 378.5,606Q421,572 435,520L560,520L618,561L700,500L771,555L846,480L806,440L435,440Q421,388 378.5,354Q336,320 280,320Q214,320 167,367Q120,414 120,480Q120,546 167,593Q214,640 280,640Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M160,160L240,320L360,320L280,160L360,160L440,320L560,320L480,160L560,160L640,320L760,320L680,160L800,160Q833,160 856.5,183.5Q880,207 880,240L880,720Q880,753 856.5,776.5Q833,800 800,800L160,800Q127,800 103.5,776.5Q80,753 80,720L80,240Q80,207 103.5,183.5Q127,160 160,160ZM160,400L160,720Q160,720 160,720Q160,720 160,720L800,720Q800,720 800,720Q800,720 800,720L800,400L160,400ZM160,400L160,400L160,720Q160,720 160,720Q160,720 160,720L160,720Q160,720 160,720Q160,720 160,720L160,400Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M287,793Q240,746 240,680Q240,614 287,567Q334,520 400,520Q423,520 442.5,525.5Q462,531 480,542L480,120L720,120L720,280L560,280L560,680Q560,746 513,793Q466,840 400,840Q334,840 287,793Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M344,710L344,344L224,344L224,280L532,280L532,344L412,344L412,710L344,710ZM688,720Q644,720 619,694.5Q594,669 594,624L594,462L540,462L540,404L594,404L594,317L660,317L660,404L734,404L734,462L660,462L660,610Q660,633 670.5,646Q681,659 699,659Q708,659 717.5,655.5Q727,652 736,646L736,711Q726,716 714,718Q702,720 688,720Z"/>
</vector>

View file

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M440,840L440,600L520,600L520,680L840,680L840,760L520,760L520,840L440,840ZM120,760L120,680L360,680L360,760L120,760ZM280,600L280,520L120,520L120,440L280,440L280,360L360,360L360,600L280,600ZM440,520L440,440L840,440L840,520L440,520ZM600,360L600,120L680,120L680,200L840,200L840,280L680,280L680,360L600,360ZM120,280L120,200L520,200L520,280L120,280Z"/>
</vector>

View file

@ -1,11 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M280,760L280,680L564,680Q627,680 673.5,640Q720,600 720,540Q720,480 673.5,440Q627,400 564,400L312,400L416,504L360,560L160,360L360,160L416,216L312,320L564,320Q661,320 730.5,383Q800,446 800,540Q800,634 730.5,697Q661,760 564,760L280,760Z"/>
</vector>

View file

@ -1,67 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="3000"
android:viewportHeight="3000"
android:tint="?attr/colorControlNormal">
<path
android:pathData="M1143.5 935L1154 935.5L1136.5 937Q1130 940 1120.5 940Q1097.2 945.2 1077.5 954Q1029.9 975.4 997 1011.5Q970.8 1039.8 954 1077.5Q945.2 1097.2 940 1120.5L937 1136.5L935.5 1155L935 1143.5L936 1142.5L936 1135.5L939 1119.5L944 1100.5Q952 1075.5 964 1054.5Q982.6 1021.6 1009.5 997Q1038.1 970.1 1076.5 953L1107.5 942L1143.5 935Z"
android:fillColor="#FFFFFF"
android:fillAlpha="0.9960784"
android:strokeColor="#FFFFFF"
android:strokeAlpha="0.9960784"
android:strokeWidth="1" />
<path
android:pathData="M1459.5 935L1460 1460L935 1459.5L1459 1459L1459.5 935Z"
android:fillColor="#FFFFFF"
android:fillAlpha="0.9960784"
android:strokeColor="#FFFFFF"
android:strokeAlpha="0.9960784"
android:strokeWidth="1" />
<path
android:pathData="M1540.5 935L1541 1459L2064 1459L2064 1154.5L2063 1153.5L2063 1144.5L2062 1143.5L2062 1136.5L2059 1120.5Q2053.8 1097.2 2045 1077.5Q2024 1030.5 1988.5 998Q1959.9 971.1 1921.5 954L1900.5 946L1878.5 940Q1869 940 1862.5 937L1845 935.5L1855.5 935L1856.5 936L1863.5 936Q1870 939 1879.5 939L1901.5 945Q1924.8 952.7 1944.5 964Q1977.4 982.6 2002 1009.5Q2028.9 1038.1 2046 1076.5Q2054.8 1096.2 2060 1119.5L2063 1135.5L2063 1142.5L2064 1143.5L2064 1153L2066 1153.5L2066 1459L2063.5 1460L1540 1460L1540.5 935Z"
android:fillColor="#FFFFFF"
android:fillAlpha="0.9960784"
android:strokeColor="#FFFFFF"
android:strokeAlpha="0.9960784"
android:strokeWidth="1" />
<path
android:pathData="M935.5 1540L1460 1540L1460 2063.5L1459 2066L1153.5 2066L1152.5 2064L1143.5 2064L1142.5 2063L1135.5 2063L1119.5 2060L1100.5 2055Q1075.5 2047 1054.5 2035Q1021.6 2016.4 997 1989.5Q970.1 1960.9 953 1922.5Q944.2 1902.8 939 1879.5L936 1863.5L936 1856.5L935 1855.5L935 1845.5L936 1845.5L936 1854.5L937 1855.5L937 1862.5L940 1878.5Q945.2 1901.8 954 1921.5Q975 1968.5 1010.5 2001Q1039.1 2027.9 1077.5 2045L1101.5 2054L1136.5 2062L1153.5 2063L1154.5 2064L1459 2064L1459 1541L935.5 1541L935.5 1540Z"
android:fillColor="#FFFFFF"
android:fillAlpha="0.9960784"
android:strokeColor="#FFFFFF"
android:strokeAlpha="0.9960784"
android:strokeWidth="1" />
<path
android:pathData="M1540 1540L2063.5 1540L2066 1541L2066 1845.5L2064 1846.5L2064 1855.5L2063 1856.5L2063 1863.5L2060 1879.5L2055 1898.5Q2047 1923.5 2035 1944.5Q2016.4 1977.4 1989.5 2002Q1960.9 2028.9 1922.5 2046L1901.5 2054L1879.5 2060L1863.5 2063L1856.5 2063L1855.5 2064L1846 2064L1845.5 2066L1541 2066L1540 2063.5L1540 1540ZM1541 1541L1541 2064L1845 2064L1846 2063L1863 2062L1891 2056L1922 2045Q1960 2028 1989 2001Q2024 1968 2045 1922Q2054 1902 2059 1879L2062 1863L2062 1856L2063 1855L2063 1846L2064 1845L2064 1541L1541 1541Z"
android:fillColor="#FFFFFF"
android:fillAlpha="0.9960784"
android:strokeColor="#FFFFFF"
android:strokeAlpha="0.9960784"
android:strokeWidth="1" />
<path
android:pathData="M540.5 348L2459.5 348L2460.5 349L2469.5 349L2470.5 350L2482.5 351L2508.5 357Q2530.5 363.5 2549.5 373Q2592.9 395.1 2624 429.5Q2651.6 459.4 2669 499.5Q2677.8 519.7 2683 543.5L2687 566.5L2687 575.5L2688 576.5L2688 2423.5L2687 2424.5L2685 2446.5L2679 2472.5L2664 2511.5Q2641.7 2556.2 2606.5 2588Q2576.6 2615.6 2536.5 2633Q2516.3 2641.8 2492.5 2647L2469.5 2651L2460.5 2651L2459.5 2652L540.5 2652L539.5 2651L530.5 2651L529.5 2650L517.5 2649L491.5 2643Q468.3 2636.2 448.5 2626Q406.4 2604.1 376 2570.5Q348.4 2540.6 331 2500.5Q322.2 2480.3 317 2456.5L313 2433.5L313 2424.5L312 2423.5L312 576.5L313 575.5L313 566.5L314 565.5L315 553.5L321 527.5Q327.5 505.5 337 486.5Q359.1 443.1 393.5 412L406.5 401L410 400Q408.9 397.3 411.5 398Q438.2 376.2 473.5 363L507.5 353L530.5 349L539.5 349L540.5 348ZM950 841L927 845L907 852Q884 862 867 877L853 892Q854 894 852 893L838 913L831 927L824 950L824 952L822 956L821 971L820 972L820 2029L821 2030L821 2038L823 2048L823 2050L825 2053L825 2057L831 2074L838 2088L850 2106L853 2107L857 2114Q888 2149 946 2159L2055 2159L2079 2154L2082 2152L2091 2150L2114 2138L2131 2125Q2154 2105 2168 2075L2177 2047L2178 2036L2179 2035L2179 2026L2180 2025L2180 976L2179 975L2179 965L2177 954L2168 926Q2159 905 2145 890Q2130 872 2110 860L2084 848L2065 843L2052 842L2051 841L950 841Z"
android:fillColor="#FFFFFF"
android:strokeColor="#FFFFFF"
android:strokeWidth="1" />
<path
android:pathData="M1154.5 935L1459 935L1459 1459L935 1459L935 1155.5L936 1154.5L936 1144.5L937 1143.5L937 1136.5L940 1120.5Q945.2 1097.2 954 1077.5Q975 1030.5 1010.5 998Q1039.1 971.1 1077.5 954Q1097.2 945.2 1120.5 940Q1130 940 1136.5 937L1143.5 937L1144.5 936L1153.5 936L1154.5 935Z"
android:fillColor="#FFFFFF"
android:strokeColor="#FFFFFF"
android:strokeWidth="1" />
<path
android:pathData="M1541 935L1844.5 935L1845.5 936L1862.5 937Q1869 940 1878.5 940L1906.5 948L1943.5 965Q1976.4 983.6 2001 1010.5Q2027.9 1039.1 2045 1077.5L2054 1101.5L2062 1136.5L2063 1153.5L2064 1154.5L2064 1459L1541 1459L1541 935Z"
android:fillColor="#FFFFFF"
android:strokeColor="#FFFFFF"
android:strokeWidth="1" />
<path
android:pathData="M935 1541L1459 1541L1459 2064L1154.5 2064L1153.5 2063L1136.5 2062L1120.5 2059L1092.5 2051L1055.5 2034Q1022.6 2015.4 998 1988.5Q971.1 1959.9 954 1921.5L945 1897.5L937 1862.5L936 1845.5L935 1844.5L935 1541Z"
android:fillColor="#FFFFFF"
android:strokeColor="#FFFFFF"
android:strokeWidth="1" />
<path
android:pathData="M1541 1541L2064 1541L2064 1844.5L2063 1845.5L2063 1854.5L2062 1855.5L2062 1862.5L2059 1878.5Q2053.8 1901.8 2045 1921.5Q2024 1968.5 1988.5 2001Q1959.9 2027.9 1921.5 2045L1890.5 2056L1862.5 2062L1845.5 2063L1844.5 2064L1541 2064L1541 1541Z"
android:fillColor="#FFFFFF"
android:strokeColor="#FFFFFF"
android:strokeWidth="1" />
</vector>

View file

@ -1,11 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M200,840Q167,840 143.5,816.5Q120,793 120,760L120,200Q120,167 143.5,143.5Q167,120 200,120L760,120Q793,120 816.5,143.5Q840,167 840,200L840,760Q840,793 816.5,816.5Q793,840 760,840L200,840ZM200,760L760,760Q760,760 760,760Q760,760 760,760L760,280L200,280L200,760Q200,760 200,760Q200,760 200,760ZM280,480L280,400L680,400L680,480L280,480ZM280,640L280,560L520,560L520,640L280,640Z"/>
</vector>

View file

@ -1,308 +0,0 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context=".settings.EqualizerActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior">
<com.google.android.material.appbar.CollapsingToolbarLayout
style="@style/App.CollapsingToolbarLarge"
app:title="@string/equalizer">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
style="@style/App.CollapsingMaterialToolbar"
app:navigationIcon="@drawable/arrow_back_rounded_24px" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="100dp"
android:paddingHorizontal="16dp"
android:animateLayoutChanges="true">
<LinearLayout
android:id="@+id/ln_upper_treble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingHorizontal="16dp">
<TextView
android:id="@+id/tv_upper_treble"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/upper_treble"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_upper_treble_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0 dB"
android:textSize="18sp" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/slider_upper_treble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:value="0.0"
android:valueFrom="-10"
android:valueTo="10" />
</LinearLayout>
<LinearLayout
android:id="@+id/ln_treble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingHorizontal="16dp">
<TextView
android:id="@+id/tv_treble"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/treble"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_treble_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0 dB"
android:textSize="18sp" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/slider_treble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:value="0.0"
android:valueFrom="-10"
android:valueTo="10" />
</LinearLayout>
<LinearLayout
android:id="@+id/ln_mid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingHorizontal="16dp">
<TextView
android:id="@+id/tv_mid"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/mid"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_mid_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0 dB"
android:textSize="18sp" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/slider_mid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:value="0.0"
android:valueFrom="-10"
android:valueTo="10" />
</LinearLayout>
<LinearLayout
android:id="@+id/ln_bass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingHorizontal="16dp">
<TextView
android:id="@+id/tv_bass"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/bass"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_bass_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0 dB"
android:textSize="18sp" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/slider_bass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:value="0.0"
android:valueFrom="-10"
android:valueTo="10" />
</LinearLayout>
<LinearLayout
android:id="@+id/ln_low_bass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingHorizontal="16dp">
<TextView
android:id="@+id/tv_low_bass"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/low_bass"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_low_bass_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0 dB"
android:textSize="18sp" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/slider_low_bass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:value="0.0"
android:valueFrom="-10"
android:valueTo="10" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginVertical="16dp" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:src="@drawable/info_24px" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/equalizer_note" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<View
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="?attr/colorSurfaceContainerLow"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Filled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:backgroundTint="?attr/colorSecondaryContainer"
app:cardCornerRadius="50dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/ln_enabled"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:paddingVertical="16dp"
android:paddingLeft="32dp"
android:paddingRight="20dp" >
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/use_equalizer"
android:textSize="16sp">
</TextView>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sw_enabled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/colorAccent"
android:clickable="false"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:id="@+id/ln_unsupport"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="?attr/colorSurfaceContainerLow"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/graphic_eq_off_96px"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:gravity="center"
android:text="@string/your_device_is_not_supported"
android:textSize="18sp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_exit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ok"/>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,217 +0,0 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context=".settings.FilePickerSettingsActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior">
<com.google.android.material.appbar.CollapsingToolbarLayout
style="@style/App.CollapsingToolbarLarge"
app:title="@string/file_picker">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
style="@style/App.CollapsingMaterialToolbar" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="108dp"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical"
android:animateLayoutChanges="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_resume"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/object_shape_top_high"
android:padding="16dp"
android:layout_marginBottom="2dp" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/sw_resume"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/resume"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/file_picker_resume_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sw_resume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:clickable="false"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp"
android:layout_marginBottom="2dp" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/sw_divider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/divider"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/file_picker_divier_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sw_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:clickable="false"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_show_hidden_files"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/object_shape_bottom_high"
android:padding="16dp"
android:layout_marginBottom="2dp" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/sw_show_hidden_files"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/show_hidden_files"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/show_hidden_files_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sw_show_hidden_files"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:clickable="false"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<View
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="?attr/colorSurfaceContainerLow"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Filled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:backgroundTint="?attr/colorSecondaryContainer"
app:cardCornerRadius="50dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="@+id/ln_enabled"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:paddingVertical="16dp"
android:paddingLeft="32dp"
android:paddingRight="20dp" >
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/use_file_picker"
android:textSize="16sp">
</TextView>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sw_enabled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/colorAccent"
android:clickable="false"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -6,7 +6,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.drawerlayout.widget.DrawerLayout
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -26,8 +28,7 @@
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/home_drawer_menu"
app:itemTextAppearanceActiveBoldEnabled="false" />
app:menu="@menu/home_drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>

View file

@ -150,43 +150,6 @@
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ln_file_picker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp"
android:gravity="center_vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="@drawable/settings_system_background_icon"
android:src="@drawable/folder_24px" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/file_picker"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/file_picker_settings_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ln_system"
android:layout_width="match_parent"
@ -339,7 +302,7 @@
android:id="@+id/ln_x11"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="18dp"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_bottom_high"
android:padding="16dp"
android:gravity="center_vertical">
@ -371,43 +334,6 @@
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ln_equalizer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_single_high"
android:padding="16dp"
android:gravity="center_vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="@drawable/settings_system_background_icon"
android:src="@drawable/graphic_eq_24px" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/equalizer"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/equalizer_settings_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -58,74 +58,87 @@
android:orientation="vertical"
android:padding="8dp">
<LinearLayout
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:orientation="vertical"
android:padding="16dp"
android:background="@drawable/object_shape_top_high">
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
<com.google.android.material.card.MaterialCardView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center_horizontal"
android:layout_marginVertical="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/ivIcon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_computer_180dp_with_padding" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom|end">
<ImageView
android:id="@+id/ivAddThubnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/backgroud_round_only_left_25_black_50_style"
android:padding="4dp"
app:srcCompat="@drawable/round_add_24"
app:tint="@android:color/white" />
</LinearLayout>
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/titleField"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/rom_name"
android:theme="@style/AppTheme.TextInput"
app:startIconDrawable="@drawable/edit_24px">
android:orientation="vertical"
android:padding="16dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/title"
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/personalization" />
<com.google.android.material.card.MaterialCardView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center_horizontal"
android:layout_marginVertical="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/ivIcon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_computer_180dp_with_padding" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom|end">
<ImageView
android:id="@+id/ivAddThubnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/backgroud_round_only_left_25_black_50_style"
android:padding="4dp"
app:srcCompat="@drawable/round_add_24"
app:tint="@android:color/white" />
</LinearLayout>
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/titleField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
android:hint="@string/rom_name"
android:theme="@style/AppTheme.TextInput"
app:startIconDrawable="@drawable/edit_24px">
</LinearLayout>
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/opencqcm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:layout_marginVertical="8dp"
android:background="@drawable/object_shape_single_high"
android:padding="16dp">
<LinearLayout
@ -156,171 +169,378 @@
android:id="@+id/opencqcm_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/open_in_new_24px"
android:src="@drawable/keyboard_arrow_right_24px"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_board"
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
android:paddingTop="16dp">
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/board"
android:textSize="18sp" />
android:paddingHorizontal="16dp"
android:paddingBottom="8dp"
android:text="@string/board" />
<TextView
android:layout_width="wrap_content"
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_cpu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/board_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
app:title="@string/processor"
app:subtitle="@string/defaulttext" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_core"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/cores"
app:subtitle="@string/defaulttext" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_thread"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/threads"
app:subtitle="@string/defaulttext" />
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="16dp"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_battery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/battery"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_storage"
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
android:paddingTop="16dp">
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/storage"
android:textSize="18sp" />
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:text="@string/storage" />
<TextView
android:layout_width="wrap_content"
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/driveField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/storage_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/hard_drive_0"
android:theme="@style/AppTheme.TextInput"
app:endIconContentDescription="@string/make_image"
app:endIconDrawable="@drawable/add_24px"
app:endIconMode="custom"
app:startIconDrawable="@drawable/hard_drive_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/drive"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_hd1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/hard_drive_1"
android:theme="@style/AppTheme.TextInput"
app:endIconContentDescription="@string/make_image"
app:endIconDrawable="@drawable/add_24px"
app:endIconMode="custom"
app:startIconDrawable="@drawable/hard_drive_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_hd1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="10dp"
android:layout_marginHorizontal="16dp"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/cdromField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/optical_drive_0"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/album_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/cdrom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_cdrom_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/optical_drive_1"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/album_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_cdrom_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:id="@+id/ln_floppy_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="16dp"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_fda"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/floppy_drive_a"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/save_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_fda"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_fdb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingHorizontal="16dp"
android:clickable="true"
android:focusable="true"
android:hint="@string/floppy_drive_b"
android:theme="@style/AppTheme.TextInput"
app:endIconDrawable="@drawable/close_24px"
app:startIconDrawable="@drawable/save_24px">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tie_fdb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:editable="false"
android:focusable="false"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginHorizontal="16dp"/>
<com.vectras.vm.view.SwitchView
android:id="@+id/sv_shared_folder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/shared_folder"
app:subtitle="SharedFolder/"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_network"
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
android:paddingTop="16dp">
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/network"
android:textSize="18sp" />
android:paddingHorizontal="16dp"
android:paddingBottom="8dp"
android:text="@string/boot" />
<TextView
android:layout_width="wrap_content"
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_bootfrom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/network_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
app:title="@string/boot_from"
app:subtitle="@string/defaulttext" />
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_showbootmenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/show_boot_menu"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_uselocaltime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/use_local_time"
app:setChecked="true"/>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
android:layout_marginHorizontal="16dp"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_useuefi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/use_uefi_for_x64_only"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_use_default_bios"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/use_default_bios_uefi"
app:setChecked="true" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_firmware"
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewFilledStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
android:layout_marginVertical="8dp"
app:cardBackgroundColor="?attr/colorCard">
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
android:padding="16dp">
<TextView
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/firmware"
android:textSize="18sp" />
android:paddingBottom="16dp"
android:text="@string/advanced" />
<TextView
android:layout_width="wrap_content"
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/qemuField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/firmware_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
android:hint="@string/qemu_params"
android:theme="@style/AppTheme.TextInput"
app:startIconDrawable="@drawable/ic_qemu">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/qemu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:inputType="none"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_advanced"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_bottom_high"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/advanced"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/advanced_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:id="@+id/lineardisclaimer"
@ -328,13 +548,13 @@
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:gravity="center_vertical"
android:paddingVertical="8dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:src="@drawable/verified_user_24px" />
<TextView

View file

@ -6,7 +6,8 @@
android:paddingVertical="8dp"
android:paddingStart="16dp"
android:paddingEnd="8dp"
android:gravity="center_vertical">
android:gravity="center_vertical"
android:background="?attr/selectableItemBackground">
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
@ -17,6 +18,5 @@
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:saveEnabled="false"
android:clickable="false"/>
</LinearLayout>

View file

@ -99,14 +99,6 @@
android:text="@string/free_palistine"
android:textSize="16sp" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_open_source_licenses"
style="?attr/buttonBarNegativeButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/open_source_licenses"/>
</LinearLayout>
</LinearLayout>

View file

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:text="@string/advanced" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/qemuField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:hint="@string/qemu_params"
android:theme="@style/AppTheme.TextInput"
app:startIconDrawable="@drawable/ic_qemu">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/qemu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:inputType="none"
android:selectAllOnFocus="true"
android:singleLine="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -1,99 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/board" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_machine"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:title="@string/machine_type"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_single_high"/>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_cpu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:title="@string/processor"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_top_high"/>
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_core"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:title="@string/cores"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_middle_high"/>
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_thread"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/threads"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_middle_high"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_nested_virtualization"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
app:setText="@string/nested_virtualization"
android:background="@drawable/object_shape_bottom_high"/>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp" />
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_battery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/battery"
android:background="@drawable/object_shape_single_high"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -1,86 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/firmware" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_bootfrom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:title="@string/boot_from"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_top_high"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_showbootmenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:setText="@string/show_boot_menu"
android:background="@drawable/object_shape_middle_high"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_uselocaltime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:setText="@string/use_local_time"
app:setChecked="true"
android:background="@drawable/object_shape_bottom_high"/>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp" />
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_useuefi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:setText="@string/use_uefi_for_x64_only"
android:background="@drawable/object_shape_top_high"/>
<com.vectras.vm.view.CheckBoxView
android:id="@+id/cbv_use_default_bios"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setText="@string/use_default_bios_uefi"
app:setChecked="true"
android:background="@drawable/object_shape_bottom_high"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

Some files were not shown because too many files have changed in this diff Show more