pre-release 9.3.14 alpha
@@ -0,0 +1,22 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact type="jar" name="XiaoMiTool:jar2">
|
||||
<output-path>$PROJECT_DIR$/out/artifacts/XiaoMiTool_jar2</output-path>
|
||||
<root id="archive" name="XiaoMiTool.jar">
|
||||
<element id="directory" name="META-INF">
|
||||
<element id="file-copy" path="$PROJECT_DIR$/src_rel2/META-INF/MANIFEST.MF" />
|
||||
</element>
|
||||
<element id="module-output" name="XiaoMiTool" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/json/json/20180130/json-20180130.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-io/commons-io/2.6/commons-io-2.6.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/commons/commons-compress/1.17/commons-compress-1.17.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/httpcomponents/httpclient/4.5.5/httpclient-4.5.5.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/apache/httpcomponents/httpcore/4.4.9/httpcore-4.4.9.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-logging/commons-logging/1.2/commons-logging-1.2.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.10/commons-codec-1.10.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/mortennobel/java-image-scaling/0.8.6/java-image-scaling-0.8.6.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/jhlabs/filters/2.0.235/filters-2.0.235.jar" path-in-jar="/" />
|
||||
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.11/commons-codec-1.11.jar" path-in-jar="/" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
@@ -0,0 +1,11 @@
|
||||
<component name="libraryTable">
|
||||
<library name="com.mortennobel:java-image-scaling:0.8.6" type="repository">
|
||||
<properties maven-id="com.mortennobel:java-image-scaling:0.8.6" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/mortennobel/java-image-scaling/0.8.6/java-image-scaling-0.8.6.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/jhlabs/filters/2.0.235/filters-2.0.235.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="jMTPe">
|
||||
<CLASSES>
|
||||
<root url="file://$PROJECT_DIR$/../../jMTPe" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<NATIVE>
|
||||
<root url="file://$PROJECT_DIR$/../../jMTPe" />
|
||||
</NATIVE>
|
||||
<SOURCES />
|
||||
<jarDirectory url="file://$PROJECT_DIR$/../../jMTPe" recursive="false" />
|
||||
</library>
|
||||
</component>
|
||||
@@ -0,0 +1,13 @@
|
||||
<component name="libraryTable">
|
||||
<library name="lib">
|
||||
<CLASSES>
|
||||
<root url="file://$PROJECT_DIR$/openjfx/lib" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="file://$PROJECT_DIR$/openjfx/lib" />
|
||||
</SOURCES>
|
||||
<jarDirectory url="file://$PROJECT_DIR$/openjfx/lib" recursive="false" />
|
||||
<jarDirectory url="file://$PROJECT_DIR$/openjfx/lib" recursive="false" type="SOURCES" />
|
||||
</library>
|
||||
</component>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_10" default="false" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_10" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
|
||||
<orderEntry type="jdk" jdkName="11" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="org.apache.commons:commons-lang3:3.7" level="project" />
|
||||
<orderEntry type="library" name="org.apache.httpcomponents:httpclient:4.5.5" level="project" />
|
||||
@@ -23,5 +23,7 @@
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" name="com.mortennobel:java-image-scaling:0.8.6" level="project" />
|
||||
<orderEntry type="library" name="lib" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,8 +1,8 @@
|
||||
-injars out\artifacts\XiaoMiTool_jar\XiaoMiTool.jar
|
||||
-outjars out\artifacts\XiaoMiTool.jar
|
||||
-injars out\artifacts\XiaoMiTool_jar2\XiaoMiTool.jar
|
||||
-outjars out\artifacts\XiaoMiTool_jar2\XiaoMiTool_guarded.jar
|
||||
|
||||
-libraryjars 'C:\Program Files\Java\jdk1.8.0_172\jre\lib\rt.jar'
|
||||
-libraryjars 'C:\Program Files\Java\jdk1.8.0_172\jre\lib\ext\jfxrt.jar'
|
||||
-libraryjars 'C:\Program Files\Java\jdk-11\jmods'
|
||||
-libraryjars out\artifacts\XiaoMiTool_jar2\openjfx-jmods
|
||||
|
||||
-dontshrink
|
||||
-dontoptimize
|
||||
@@ -30,8 +30,6 @@
|
||||
<methods>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Keep - Applications. Keep all application classes, along with their 'main' methods.
|
||||
-keepclasseswithmembers public class * {
|
||||
public static void main(java.lang.String[]);
|
||||
@@ -58,6 +56,20 @@
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
# Remove - System method calls. Remove all invocations of System
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.System {
|
||||
public static long currentTimeMillis();
|
||||
static java.lang.Class getCallerClass();
|
||||
public static int identityHashCode(java.lang.Object);
|
||||
public static java.lang.SecurityManager getSecurityManager();
|
||||
public static java.util.Properties getProperties();
|
||||
public static java.lang.String getProperty(java.lang.String);
|
||||
public static java.lang.String getenv(java.lang.String);
|
||||
public static java.lang.String mapLibraryName(java.lang.String);
|
||||
public static java.lang.String getProperty(java.lang.String,java.lang.String);
|
||||
}
|
||||
|
||||
# Remove - Math method calls. Remove all invocations of Math
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.Math {
|
||||
@@ -306,21 +318,6 @@
|
||||
public java.lang.String substring(int,int);
|
||||
}
|
||||
|
||||
# Remove - System method calls. Remove all invocations of System
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.System {
|
||||
public static long currentTimeMillis();
|
||||
static java.lang.Class getCallerClass();
|
||||
public static int identityHashCode(java.lang.Object);
|
||||
public static java.lang.SecurityManager getSecurityManager();
|
||||
public static java.util.Properties getProperties();
|
||||
public static java.lang.String getProperty(java.lang.String);
|
||||
public static java.lang.String getenv(java.lang.String);
|
||||
public static java.lang.String mapLibraryName(java.lang.String);
|
||||
public static java.lang.String getProperty(java.lang.String,java.lang.String);
|
||||
|
||||
}
|
||||
|
||||
-assumenosideeffects public class com.xiaomitool.v2.logging.Log {
|
||||
public static *** debug(...);
|
||||
public static *** debug(...);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class AdbCommons {
|
||||
return runner.getOutputString();
|
||||
}
|
||||
|
||||
private static String adb_shellWithOr(String cmd, String device, int timeout){
|
||||
public static String adb_shellWithOr(String cmd, String device, int timeout){
|
||||
cmd += " || echo "+CHECK_RETURN_CODE;
|
||||
String output = adb_shell(cmd, device, timeout);
|
||||
return (output == null || output.contains(CHECK_RETURN_CODE)) ? null : output;
|
||||
|
||||
@@ -12,18 +12,23 @@ import java.util.Map;
|
||||
|
||||
public class AdbCommunication {
|
||||
public static Thread trackDevicesThread, refreshDevicesThread;
|
||||
private static boolean canInterrupt = true, isTrackDeviceActive=false;
|
||||
private static int cannotInterruptCount = 0; private static boolean isTrackDeviceActive=false;
|
||||
private static final int REFRESH_TIME_MS = 2500;
|
||||
private static AdbRunner trackDeviceProcess;
|
||||
private static final Object sync = new Object();
|
||||
public static boolean canInterrupt(){
|
||||
return cannotInterruptCount == 0;
|
||||
}
|
||||
|
||||
public static void startServer(){
|
||||
if (!canInterrupt){
|
||||
if (!canInterrupt()){
|
||||
Log.debug("Cannot interrupt adb connection");
|
||||
}
|
||||
AdbCommons.start_server();
|
||||
|
||||
}
|
||||
public static void killServer(){
|
||||
if (!canInterrupt){
|
||||
if (!canInterrupt()){
|
||||
Log.debug("Cannot interrupt adb connection");
|
||||
return;
|
||||
}
|
||||
@@ -34,14 +39,14 @@ public class AdbCommunication {
|
||||
startServer();
|
||||
}
|
||||
|
||||
public static boolean canInterrupt() {
|
||||
return canInterrupt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void registerAutoScanDevices(){
|
||||
if (refreshDevicesThread != null){
|
||||
return;
|
||||
synchronized (sync) {
|
||||
if (refreshDevicesThread != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Runnable trackDevices = new Runnable() {
|
||||
@Override
|
||||
@@ -109,15 +114,19 @@ public class AdbCommunication {
|
||||
refreshFastbootDevices();
|
||||
}
|
||||
|
||||
public static void closeAccess() {
|
||||
canInterrupt = false;
|
||||
public static void getAllAccess() {
|
||||
cannotInterruptCount++;
|
||||
unregisterAutoScanDevices();
|
||||
}
|
||||
public static void openAccess(){
|
||||
canInterrupt = true;
|
||||
registerAutoScanDevices();
|
||||
public static void giveAllAccess(){
|
||||
if (cannotInterruptCount > 0){
|
||||
cannotInterruptCount--;
|
||||
}
|
||||
if (canInterrupt()) {
|
||||
registerAutoScanDevices();
|
||||
}
|
||||
}
|
||||
private static void unregisterAutoScanDevices(){
|
||||
public static void unregisterAutoScanDevices(){
|
||||
if (trackDeviceProcess != null){
|
||||
trackDeviceProcess.kill();
|
||||
}
|
||||
|
||||
@@ -183,4 +183,15 @@ public class FastbootCommons {
|
||||
}
|
||||
return flash(serial,dummyPath.toFile(), "antirbpass");
|
||||
}
|
||||
public static boolean oemRebootRecovery(String serial){
|
||||
FastbootRunner runner = FastbootCommons.command_fast(serial,5,"oem","reboot-recovery");
|
||||
if (runner == null || runner.getExitValue() != 0){
|
||||
return false;
|
||||
}
|
||||
String out = runner.getOutputString();
|
||||
if (out == null || out.toLowerCase().contains("fail")){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import com.xiaomitool.v2.adb.AdbCommons;
|
||||
import com.xiaomitool.v2.adb.AdbException;
|
||||
import com.xiaomitool.v2.adb.FastbootCommons;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.NotNull;
|
||||
import com.xiaomitool.v2.utility.WaitSemaphore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Device {
|
||||
|
||||
@@ -104,6 +104,8 @@ public class Device {
|
||||
isConnected = connected;
|
||||
if (connected){
|
||||
deviceActiveSem.setPermits(1);
|
||||
} else {
|
||||
deviceActiveSem.setPermits(0);
|
||||
}
|
||||
}
|
||||
public boolean isConnected() {
|
||||
@@ -135,6 +137,7 @@ public class Device {
|
||||
return rebootNoWait(toStatus, false);
|
||||
}
|
||||
private boolean rebootInternal(Status toStatus, boolean wait) throws InterruptedException, AdbException {
|
||||
deviceActiveSem.setPermits(0);
|
||||
if (Status.FASTBOOT.equals(this.status)){
|
||||
return fastbootReboot(toStatus, wait);
|
||||
} else {
|
||||
@@ -144,26 +147,30 @@ public class Device {
|
||||
private boolean fastbootReboot(Status toStatus, boolean wait) throws AdbException, InterruptedException {
|
||||
if (Status.FASTBOOT.equals(toStatus)){
|
||||
FastbootCommons.rebootBootloader(serial);
|
||||
return rebootWait(toStatus);
|
||||
return wait ? rebootWait(toStatus) : true;
|
||||
} else if (Status.EDL.equals(toStatus)){
|
||||
FastbootCommons.oemEdl(serial);
|
||||
return rebootWait(toStatus);
|
||||
} else {
|
||||
if (!Status.DEVICE.equals(toStatus) && !wait){
|
||||
throw new AdbException("Cannot reboot from fastboot to "+toStatus.toString()+" without waiting");
|
||||
return wait ? rebootWait(toStatus) : true;
|
||||
} else if (Status.SIDELOAD.equals(toStatus) || Status.RECOVERY.equals(toStatus)){
|
||||
if (FastbootCommons.oemRebootRecovery(serial)){
|
||||
return wait ? rebootNoWait(toStatus) : true;
|
||||
}
|
||||
FastbootCommons.reboot(serial);
|
||||
if (!wait){
|
||||
}
|
||||
if (!Status.DEVICE.equals(toStatus) && !wait){
|
||||
throw new AdbException("Cannot reboot from fastboot to "+toStatus.toString()+" without waiting");
|
||||
}
|
||||
FastbootCommons.reboot(serial);
|
||||
if (!wait){
|
||||
return true;
|
||||
}
|
||||
if (!rebootWait(Status.DEVICE)){
|
||||
if (isConnected && toStatus.equals(this.status)){
|
||||
return true;
|
||||
}
|
||||
if (!rebootWait(Status.DEVICE)){
|
||||
if (isConnected && toStatus.equals(this.status)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return reboot(toStatus,false);
|
||||
return false;
|
||||
}
|
||||
return reboot(toStatus,false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +190,8 @@ public class Device {
|
||||
String status = toStatus.toString();
|
||||
if (Status.FASTBOOT.equals(toStatus)){
|
||||
status = "bootloader";
|
||||
} else if (Status.SIDELOAD.equals(toStatus)){
|
||||
status = Status.RECOVERY.toString();
|
||||
}
|
||||
AdbCommons.reboot(serial,status);
|
||||
return !wait || rebootWait(toStatus);
|
||||
|
||||
@@ -4,8 +4,11 @@ import com.xiaomitool.v2.adb.AdbCommons;
|
||||
import com.xiaomitool.v2.crypto.Hash;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.process.AdbRunner;
|
||||
import com.xiaomitool.v2.rom.MiuiRom;
|
||||
import com.xiaomitool.v2.utility.YesNoMaybe;
|
||||
import com.xiaomitool.v2.utility.utils.StrUtils;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.Branch;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.MiuiVersion;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.UnlockStatus;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -108,4 +111,11 @@ public class DeviceAnswers {
|
||||
setAnswer(NEED_DEVICE_DEBUG, answer);
|
||||
}
|
||||
|
||||
public MiuiRom.Specie getCurrentSpecie() {
|
||||
String product = (String) device.getDeviceProperties().get(DeviceProperties.CODENAME);
|
||||
MiuiVersion version = MiuiVersion.fromObject(device.getDeviceProperties().get(DeviceProperties.FULL_VERSION));
|
||||
Branch branch = version == null ? Branch.DEVELOPER : version.getBranch();
|
||||
branch = branch == null ? Branch.DEVELOPER : branch;
|
||||
return MiuiRom.Specie.fromStringBranch(product,branch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,134 @@ public class DeviceGroups {
|
||||
private static final HashSet<String> ALWAYS_UNLOCKED_DEVICES = getAlwaysUnlockedSet();
|
||||
private static final HashSet<String> EEA_REGION_DEVICES = getEeaRegionDevices();
|
||||
private static final HashSet<String> ANDROID_ONE_DEVICES = getAndroidOneDevices();
|
||||
private static final HashSet<String> RECOVERY_SAFE = removeUnsafeDevices(getCurrentDevices());
|
||||
|
||||
public static boolean isSafeToChangeRecoveryLocked(String codename){
|
||||
codename = stripCodename(codename);
|
||||
for (String c : RECOVERY_SAFE){
|
||||
if (codename.startsWith(c)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final HashSet<String> removeUnsafeDevices(HashSet<String> toRemove){
|
||||
toRemove.remove("ugg");
|
||||
toRemove.remove("ugglite");
|
||||
toRemove.remove("rosy");
|
||||
toRemove.remove("riva");
|
||||
toRemove.remove("vince");
|
||||
toRemove.remove("whyred");
|
||||
toRemove.remove("versace");
|
||||
toRemove.remove("wayne");
|
||||
toRemove.remove("ysl");
|
||||
toRemove.remove("sirius");
|
||||
toRemove.remove("polaris");
|
||||
toRemove.remove("sakura");
|
||||
toRemove.remove("sakura_india");
|
||||
toRemove.remove("ursa");
|
||||
toRemove.remove("beryllium");
|
||||
toRemove.remove("comet");
|
||||
toRemove.remove("clover");
|
||||
toRemove.remove("cactus");
|
||||
toRemove.remove("cereus");
|
||||
toRemove.remove("nitrogen");
|
||||
toRemove.remove("dipper");
|
||||
toRemove.remove("tulip");
|
||||
toRemove.remove("platina");
|
||||
toRemove.remove("lilium");
|
||||
toRemove.remove("equuleus");
|
||||
toRemove.remove("perseus");
|
||||
toRemove.remove("cepheus");
|
||||
toRemove.remove("onc");
|
||||
toRemove.remove("onclite");
|
||||
toRemove.remove("lavender");
|
||||
toRemove.remove("grus");
|
||||
toRemove.remove("violet");
|
||||
toRemove.remove("davinci");
|
||||
toRemove.remove("raphael");
|
||||
return toRemove;
|
||||
}
|
||||
|
||||
private static final HashSet<String> getCurrentDevices(){
|
||||
HashSet<String> set = new HashSet<>();
|
||||
set.add("mione");
|
||||
set.add("aries");
|
||||
set.add("taurus");
|
||||
set.add("pisces");
|
||||
set.add("cancro");
|
||||
set.add("armani");
|
||||
set.add("mocha");
|
||||
set.add("hammerhead");
|
||||
set.add("dior");
|
||||
set.add("virgo");
|
||||
set.add("gucci");
|
||||
set.add("ferrari");
|
||||
set.add("leo");
|
||||
set.add("hermes");
|
||||
set.add("libra");
|
||||
set.add("latte");
|
||||
set.add("ido");
|
||||
set.add("hennessy");
|
||||
set.add("aqua");
|
||||
set.add("gemini");
|
||||
set.add("kenzo");
|
||||
set.add("capricorn");
|
||||
set.add("scorpio");
|
||||
set.add("hydrogen");
|
||||
set.add("land");
|
||||
set.add("omega");
|
||||
set.add("markw");
|
||||
set.add("nikel");
|
||||
set.add("natrium");
|
||||
set.add("lithium");
|
||||
set.add("helium");
|
||||
set.add("prada");
|
||||
set.add("mido");
|
||||
set.add("rolex");
|
||||
set.add("meri");
|
||||
set.add("sagit");
|
||||
set.add("santoni");
|
||||
set.add("cappu");
|
||||
set.add("oxygen");
|
||||
set.add("tiffany");
|
||||
set.add("jason");
|
||||
set.add("ugglite");
|
||||
set.add("ugg");
|
||||
set.add("tissot");
|
||||
set.add("chiron");
|
||||
set.add("riva");
|
||||
set.add("vince");
|
||||
set.add("rosy");
|
||||
set.add("dipper");
|
||||
set.add("whyred");
|
||||
set.add("polaris");
|
||||
set.add("wayne");
|
||||
set.add("nitrogen");
|
||||
set.add("ysl");
|
||||
set.add("sirius");
|
||||
set.add("sakura");
|
||||
set.add("cactus");
|
||||
set.add("cereus");
|
||||
set.add("beryllium");
|
||||
set.add("clover");
|
||||
set.add("ursa");
|
||||
set.add("platina");
|
||||
set.add("perseus");
|
||||
set.add("equuleus");
|
||||
set.add("cepheus");
|
||||
set.add("lotus");
|
||||
set.add("lavender");
|
||||
set.add("grus");
|
||||
return set;
|
||||
}
|
||||
|
||||
private static final HashSet<String> getAndroidOneDevices(){
|
||||
HashSet<String> set = new HashSet<>();
|
||||
set.add("tiare");
|
||||
set.add("tissot_sprout");
|
||||
set.add("jasmine_sprout");
|
||||
return set;
|
||||
}
|
||||
private static HashSet<String> getEeaRegionDevices(){
|
||||
@@ -46,7 +171,7 @@ public class DeviceGroups {
|
||||
return set;
|
||||
|
||||
}
|
||||
private static String stripCode(String codename){
|
||||
public static String stripCodename(String codename){
|
||||
if (codename == null){
|
||||
return "";
|
||||
}
|
||||
@@ -57,21 +182,21 @@ public class DeviceGroups {
|
||||
if (codename == null){
|
||||
return false;
|
||||
}
|
||||
return ALWAYS_UNLOCKED_DEVICES.contains(stripCode(codename));
|
||||
return ALWAYS_UNLOCKED_DEVICES.contains(stripCodename(codename));
|
||||
}
|
||||
|
||||
public static boolean hasEEARegion(String codename){
|
||||
if (codename == null){
|
||||
return false;
|
||||
}
|
||||
return EEA_REGION_DEVICES.contains(stripCode(codename));
|
||||
return EEA_REGION_DEVICES.contains(stripCodename(codename));
|
||||
}
|
||||
|
||||
public static boolean isAndroidOneDevice(String codename){
|
||||
if (codename == null){
|
||||
return false;
|
||||
}
|
||||
codename = stripCode(codename);
|
||||
codename = stripCodename(codename);
|
||||
return codename.contains("_sprout") || ANDROID_ONE_DEVICES.contains(codename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,12 @@ public class DeviceManager {
|
||||
public static void initScanThreads(){
|
||||
AdbCommunication.registerAutoScanDevices();
|
||||
}
|
||||
public void addDevice(Device device){
|
||||
|
||||
public static void stopScanThreads() {
|
||||
AdbCommunication.unregisterAutoScanDevices();
|
||||
}
|
||||
|
||||
public static void addDevice(Device device){
|
||||
deviceMap.put(device.getSerial(), device);
|
||||
}
|
||||
public static void setSelectedDevice(Device device){
|
||||
|
||||
@@ -17,9 +17,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ToolManager {
|
||||
public static String TOOL_VERSION = "8.9.24";
|
||||
public static String TOOL_VERSION = "9.3.14";
|
||||
public static String URL_DONATION = "https://xiaomitool.page.link/donate";
|
||||
public static String TOOL_VERSION_EX = "unbrick only";
|
||||
public static String TOOL_VERSION_EX = "alpha";
|
||||
public static String XMT_HOST = "https://www.xiaomitool.com/V2/";
|
||||
public static String URL_UPDATE = XMT_HOST+"update.php";
|
||||
public static String URL_LATEST = XMT_HOST+"latest";
|
||||
|
||||
@@ -5,8 +5,12 @@ import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.adb.device.DeviceManager;
|
||||
import com.xiaomitool.v2.adb.device.DeviceProperties;
|
||||
import com.xiaomitool.v2.engine.CommonsMessages;
|
||||
import com.xiaomitool.v2.engine.ToolManager;
|
||||
import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.PopupWindow;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.gui.deviceView.Animatable;
|
||||
import com.xiaomitool.v2.gui.deviceView.DeviceRecoveryView;
|
||||
import com.xiaomitool.v2.gui.deviceView.DeviceView;
|
||||
import com.xiaomitool.v2.gui.drawable.DrawableManager;
|
||||
import com.xiaomitool.v2.gui.other.DeviceTableEntry;
|
||||
@@ -17,8 +21,13 @@ import com.xiaomitool.v2.procedure.GuiListener;
|
||||
import com.xiaomitool.v2.procedure.ProcedureRunner;
|
||||
import com.xiaomitool.v2.procedure.RInstall;
|
||||
import com.xiaomitool.v2.procedure.RMessage;
|
||||
import com.xiaomitool.v2.procedure.device.ManageDevice;
|
||||
import com.xiaomitool.v2.procedure.device.RebootDevice;
|
||||
import com.xiaomitool.v2.procedure.install.GenericInstall;
|
||||
import com.xiaomitool.v2.procedure.install.InstallException;
|
||||
import com.xiaomitool.v2.procedure.uistuff.ChooseProcedure;
|
||||
import com.xiaomitool.v2.procedure.uistuff.ConfirmationProcedure;
|
||||
import com.xiaomitool.v2.utility.CommandClass;
|
||||
import com.xiaomitool.v2.utility.Nullable;
|
||||
import com.xiaomitool.v2.utility.RunnableMessage;
|
||||
|
||||
@@ -38,9 +47,13 @@ import javafx.scene.layout.*;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextAlignment;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static com.xiaomitool.v2.engine.CommonsMessages.NOOP;
|
||||
|
||||
|
||||
public class ActionsDynamic {
|
||||
public static RunnableMessage MAIN_SCREEN_LOADING(LRes message){
|
||||
return MAIN_SCREEN_LOADING(message.toString());
|
||||
@@ -81,7 +94,7 @@ public class ActionsDynamic {
|
||||
case RECOVERY:
|
||||
msg = LRes.NO_DEVICE_CONNECTED_RECOVERY;
|
||||
button = LRes.HT_GO_RECOVERY;
|
||||
howto = ActionsStatic.HOWTO_GO_RECOVERY();
|
||||
howto = HOWTO_GO_RECOVERY(null);
|
||||
break;
|
||||
case FASTBOOT:
|
||||
msg = LRes.NO_DEVICE_CONNECTED_FASTBOOT;
|
||||
@@ -90,6 +103,7 @@ public class ActionsDynamic {
|
||||
default:
|
||||
msg = LRes.NO_DEVICE_CONNECTED;
|
||||
button = LRes.HT_ENABLE_USB_DEBUG;
|
||||
howto = ActionsDynamic.HOW_TO_ENABLE_USB_DEBUGGING(null, DeviceManager.getDevices().isEmpty());
|
||||
|
||||
}
|
||||
ButtonPane pane = new ButtonPane(LRes.SEARCH_AGAIN, button);
|
||||
@@ -103,7 +117,7 @@ public class ActionsDynamic {
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
vBox.setSpacing(20);
|
||||
pane.setContent(vBox);
|
||||
Log.debug("SDSDSASEW");
|
||||
|
||||
WindowManager.setMainContent(pane);
|
||||
DeviceManager.addMessageReceiver(pane.getIdClickReceiver());
|
||||
int message = CommonsMessages.NOOP;
|
||||
@@ -111,7 +125,7 @@ public class ActionsDynamic {
|
||||
message=pane.waitClick();
|
||||
if (message > 0 && howto != null){
|
||||
message = howto.run();
|
||||
if (message >= 0){
|
||||
if (message == 0){
|
||||
message = NOOP;
|
||||
}
|
||||
}
|
||||
@@ -240,7 +254,7 @@ public class ActionsDynamic {
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
vBox.setSpacing(20);
|
||||
pane.setContent(vBox);
|
||||
WindowManager.setMainContent(pane);
|
||||
WindowManager.setMainContent(pane, false);
|
||||
IDClickReceiver receiver = pane.getIdClickReceiver();
|
||||
DeviceManager.addMessageReceiver(receiver);
|
||||
int message = NOOP;
|
||||
@@ -254,14 +268,16 @@ public class ActionsDynamic {
|
||||
if (message == 0){
|
||||
MAIN_SCREEN_LOADING(LRes.SEARCHING_CONNECTED_DEVICES).run();
|
||||
ActionsStatic.RESTART_ADB_SERVER().run();
|
||||
WindowManager.removeTopContent();
|
||||
if (device.isConnected()){
|
||||
break;
|
||||
}
|
||||
WindowManager.removeTopContent();
|
||||
|
||||
}
|
||||
message = NOOP;
|
||||
}
|
||||
DeviceManager.removeMessageReceiver(receiver);
|
||||
WindowManager.removeTopContent();
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
@@ -272,6 +288,7 @@ public class ActionsDynamic {
|
||||
public static RunnableMessage WAIT_USB_DEBUG_ENABLE(Device device, String text){
|
||||
return () -> {
|
||||
ButtonPane pane = new ButtonPane(LRes.HT_ENABLE_USB_DEBUG, LRes.SEARCH_AGAIN);
|
||||
pane.setContentText(LRes.WAITING_USB_ENABLE.toString(LRes.SEARCH_AGAIN));
|
||||
WindowManager.setMainContent(pane);
|
||||
IDClickReceiver receiver = pane.getIdClickReceiver();
|
||||
DeviceManager.addMessageReceiver(receiver);
|
||||
@@ -285,11 +302,18 @@ public class ActionsDynamic {
|
||||
}
|
||||
if (message == 1){
|
||||
ActionsStatic.RESTART_ADB_SERVER().run();
|
||||
if (device.isTurnedOn()){
|
||||
WindowManager.removeTopContent();
|
||||
if (device.isTurnedOn() || Device.Status.UNAUTHORIZED.equals(device.getStatus())){
|
||||
break;
|
||||
}
|
||||
WindowManager.removeTopContent();
|
||||
|
||||
|
||||
} else if (message == 0){
|
||||
if (HOW_TO_ENABLE_USB_DEBUGGING(device, true).run() > 0){
|
||||
if (device.isTurnedOn() || Device.Status.UNAUTHORIZED.equals(device.getStatus())){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message = NOOP;
|
||||
@@ -299,6 +323,52 @@ public class ActionsDynamic {
|
||||
return 0;};
|
||||
}
|
||||
|
||||
public static RunnableMessage REBOOT_STOCK_RECOVERY(Device device, boolean force){
|
||||
return new RunnableMessage() {
|
||||
@Override
|
||||
public int run() throws InterruptedException {
|
||||
|
||||
if (device == null){
|
||||
return 0;
|
||||
}
|
||||
if (!force){
|
||||
if (Device.Status.SIDELOAD.equals(device.getStatus())){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
REQUIRE_DEVICE_CONNECTED(device).run();
|
||||
REQUIRE_DEVICE_AUTH(device).run();
|
||||
if (Device.Status.FASTBOOT.equals(device.getStatus())){
|
||||
try {
|
||||
if (!device.reboot(Device.Status.DEVICE)){
|
||||
throw new AdbException("Failed to reboot device to device mode");
|
||||
}
|
||||
} catch (AdbException e) {
|
||||
REQUIRE_DEVICE_CONNECTED(device).run();
|
||||
REQUIRE_DEVICE_AUTH(device).run();
|
||||
if (!device.isTurnedOn()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
try {
|
||||
if (!device.rebootNoWait(Device.Status.SIDELOAD,force)){
|
||||
throw new AdbException("Failed to reboot device to recovery mode");
|
||||
}
|
||||
HOWTO_GO_RECOVERY(device).run();
|
||||
if(!device.waitStatus(Device.Status.SIDELOAD)){
|
||||
throw new AdbException("Failed to reboot device to recovery mode");
|
||||
}
|
||||
} catch (AdbException e) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static RunnableMessage FIND_DEVICE_INFO(Device device){
|
||||
return () -> {
|
||||
Text texts[] = new Text[10];
|
||||
@@ -354,7 +424,7 @@ public class ActionsDynamic {
|
||||
ActionsUtil.setDevicePropertiesText(device, texts);
|
||||
}
|
||||
|
||||
if (!device.getDeviceProperties().getSideloadProperties().isParsed()) {
|
||||
if (!device.getDeviceProperties().getSideloadProperties().isParsed() && !device.getDeviceProperties().getRecoveryProperties().isParsed()) {
|
||||
try {
|
||||
if (UnlockStatus.UNLOCKED.equals(device.getAnswers().getUnlockStatus())) {
|
||||
Platform.runLater(new Runnable() {
|
||||
@@ -365,11 +435,13 @@ public class ActionsDynamic {
|
||||
});
|
||||
|
||||
} else {
|
||||
if (!device.reboot(Device.Status.RECOVERY)) {
|
||||
throw new Exception("Failed to reboot to recovery");
|
||||
} else {
|
||||
ActionsUtil.setDevicePropertiesText(device, texts);
|
||||
|
||||
boolean result = REBOOT_STOCK_RECOVERY(device, true).run() != 0;
|
||||
if (!result){
|
||||
throw new Exception("Failed to reboot to stock recovery");
|
||||
}
|
||||
ActionsUtil.setDevicePropertiesText(device, texts);
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(new Runnable() {
|
||||
@@ -411,32 +483,31 @@ public class ActionsDynamic {
|
||||
|
||||
IDClickReceiver receiver = pane.getIdClickReceiver();
|
||||
DeviceManager.addMessageReceiver(receiver);
|
||||
DeviceView deviceView = new DeviceView(DeviceView.DEVICE_18_9, 900);
|
||||
DeviceView deviceView = new DeviceView(DeviceView.DEVICE_18_9, 880);
|
||||
ImageView image = new ImageView(DrawableManager.getPng(DrawableManager.DEVICE_AUTH).toString());
|
||||
image.setViewport(new Rectangle2D(0,image.getImage().getHeight()-2160,1080,2160));
|
||||
//image.setViewport(new Rectangle2D(0,image.getImage().getHeight()-2160,1080,2160));
|
||||
deviceView.setContent(image);
|
||||
deviceView.buildCircleTransition(800,2060,Animation.INDEFINITE);
|
||||
Pane cropped = GuiUtils.crop(deviceView,0,550,900/deviceView.getOuterAspectRatio(),350);
|
||||
cropped.setPrefSize(900/deviceView.getOuterAspectRatio(),350);
|
||||
GuiUtils.debug(cropped);
|
||||
|
||||
//GuiUtils.debug(cropped);
|
||||
Text text = new Text(LRes.AUTH_DEVICE_TEXT.toString());
|
||||
text.setTextAlignment(TextAlignment.CENTER);
|
||||
text.setFont(Font.font(16));
|
||||
text.setWrappingWidth(600);
|
||||
VBox vBox = new VBox(GuiUtils.center(cropped),text);
|
||||
VBox vBox = new VBox(GuiUtils.center(DeviceView.crop(deviceView,310,570)),text);
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
vBox.setSpacing(20);
|
||||
|
||||
pane.setContent(vBox);
|
||||
|
||||
WindowManager.setMainContent(pane);
|
||||
WindowManager.setMainContent(pane, false);
|
||||
|
||||
|
||||
int messsage = NOOP;
|
||||
while (messsage == NOOP){
|
||||
messsage = receiver.waitClick();
|
||||
if(messsage == CommonsMessages.DEVICE_UPDATE_FINISH){
|
||||
if (!device.needAuthorization()){
|
||||
if (!device.needAuthorization() && device.isConnected()){
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -447,16 +518,20 @@ public class ActionsDynamic {
|
||||
DeviceManager.refresh();
|
||||
if (device.needAuthorization()) {
|
||||
ActionsStatic.RESTART_ADB_SERVER().run();
|
||||
if (!device.needAuthorization()){
|
||||
if (!device.needAuthorization() && device.isConnected()){
|
||||
break;
|
||||
} else {
|
||||
WindowManager.setMainContent(pane);
|
||||
WindowManager.setMainContent(pane, false);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
messsage = NOOP;
|
||||
}
|
||||
}
|
||||
|
||||
DeviceManager.removeMessageReceiver(receiver);
|
||||
WindowManager.removeTopContent();
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
@@ -489,27 +564,159 @@ public class ActionsDynamic {
|
||||
|
||||
//runner.setContext("prop_"+DeviceProperties.CODENAME,"whyred");
|
||||
//FastbootFetch.findAllLatestFastboot().run(runner);
|
||||
RInstall main = GenericInstall.main();
|
||||
try {
|
||||
try {
|
||||
/* RebootDevice.rebootNoWaitIfConnected().run(runner);
|
||||
Log.debug("PRO0 CHOOSE CAT");
|
||||
ChooseProcedure.chooseRomCategory().run(runner);
|
||||
Log.debug("PRO0 CHOOSE ROM");
|
||||
ChooseProcedure.chooseRom().run(runner);
|
||||
Log.debug("PRO0 FETCH RESOURCE");
|
||||
ConfirmationProcedure.confirmInstallableProcedure().run(runner);
|
||||
ConfirmationProcedure.confirmInstallationStart().run(runner);
|
||||
runner.text(LRes.WAITING_DEVICE_ACTIVE);
|
||||
ManageDevice.waitDevice(60);
|
||||
GenericInstall.satisfyAllRequirements().run(runner);
|
||||
GenericInstall.resourceFetchWait().run(runner);
|
||||
Log.debug("PRO0 INSTALL ROM");
|
||||
DeviceManager.refresh();
|
||||
GenericInstall.runInstallProcedure().run(runner);
|
||||
Log.debug("PRO0 FINISHED");
|
||||
GenericInstall.installationSuccess().run(runner);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
} catch (RMessage rMessage) {
|
||||
GenericInstall.installationSuccess().run(runner);*/
|
||||
main.run(runner);
|
||||
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
runner.handleException(new InstallException(e.getMessage(), InstallException.Code.INTERNAL_ERROR, false), main);
|
||||
} catch (InstallException e1) {
|
||||
throw new RMessage(e1);
|
||||
}
|
||||
}
|
||||
}catch (RMessage rMessage) {
|
||||
Log.debug("RMSG: "+rMessage.getCmd());
|
||||
rMessage.printStackTrace();
|
||||
if (CommandClass.Command.ABORT.equals(rMessage.getCmd())){
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActionsStatic.MOD_CHOOSE_SCREEN().run();
|
||||
} catch (InterruptedException e) {
|
||||
Log.debug(e.getMessage());
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
return 0;
|
||||
}
|
||||
Stage st = WindowManager.launchPopup(new PopupWindow.ImageTextPopup("A fatal error has occured: type: "+rMessage.getCmd()+"\nThe tool will now exit",PopupWindow.Icon.ERROR));
|
||||
if (st != null){
|
||||
while (st.isShowing()){
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
}
|
||||
ToolManager.exit(1);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
public static RunnableMessage HOWTO_GO_RECOVERY(Device device){
|
||||
return HOWTO_GO_RECOVERY(true,device);
|
||||
}
|
||||
|
||||
public static RunnableMessage HOWTO_GO_RECOVERY(boolean rebootingText, Device device){
|
||||
return () -> {
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.OK_FINISHED);
|
||||
SidePane sidePane = new SidePane();
|
||||
DeviceRecoveryView deviceRecoveryView = new DeviceRecoveryView(DeviceView.DEVICE_18_9,640);
|
||||
deviceRecoveryView.animateSelectThird(3000);
|
||||
String nText;
|
||||
if (!rebootingText){
|
||||
nText = "1) "+LRes.BTN_VOLUP_POW.toString()+"\n2) "+LRes.HT_RECOVERY_TEXT_1.toString();
|
||||
} else {
|
||||
nText = LRes.ENTER_STOCK_RECOVERY_MODE.toString();
|
||||
}
|
||||
Text t = new Text(nText);
|
||||
|
||||
t.setWrappingWidth(400);
|
||||
t.setFont(Font.font(15));
|
||||
sidePane.setLeft(t);
|
||||
Pane p = DeviceView.crop(deviceRecoveryView,410);
|
||||
|
||||
//GuiUtils.debug(p);
|
||||
sidePane.setRight(GuiUtils.center(p));
|
||||
buttonPane.setContent(sidePane);
|
||||
WindowManager.setMainContent(buttonPane,false);
|
||||
DeviceManager.addMessageReceiver(buttonPane.getIdClickReceiver());
|
||||
int msg = NOOP;
|
||||
int exitcode = 0;
|
||||
while (msg < 0){
|
||||
exitcode = 0;
|
||||
|
||||
if (device != null && device.isConnected() && Device.Status.SIDELOAD.equals(device.getStatus())){
|
||||
exitcode = 1;
|
||||
break;
|
||||
}
|
||||
//Log.debug(msg+" - "+DeviceManager.count(Device.Status.SIDELOAD));
|
||||
msg = buttonPane.waitClick();
|
||||
}
|
||||
DeviceManager.removeMessageReceiver(buttonPane.getIdClickReceiver());
|
||||
WindowManager.removeTopContent();
|
||||
return exitcode;
|
||||
};
|
||||
}
|
||||
|
||||
public static RunnableMessage HOW_TO_ENABLE_USB_DEBUGGING(Device device, boolean search){
|
||||
return new RunnableMessage() {
|
||||
@Override
|
||||
public int run() throws InterruptedException {
|
||||
String[] text = new String[]{LRes.HT_ENABLE_USB_1.toString(),LRes.HT_ENABLE_USB_2.toString(),LRes.HT_ENABLE_USB_3.toString(),LRes.HT_ENABLE_USB_4.toString(),LRes.HT_ENABLE_USB_5.toString(),LRes.HT_ENABLE_USB_6.toString(),LRes.HT_ENABLE_USB_7.toString(),};
|
||||
Image[] images = new Image[7];
|
||||
for (int i = 0; i<7; i++){
|
||||
images[i] = new Image(DrawableManager.getPng("usbdbg"+(i+1)).toString(),false);
|
||||
}
|
||||
HashMap<Integer, Animatable.AnimationPayload> animations = new HashMap<>();
|
||||
animations.put(0,new Animatable.AnimationPayload(664,1323,Animation.INDEFINITE, true));
|
||||
animations.put(1,new Animatable.AnimationPayload(400,435,Animation.INDEFINITE, true));
|
||||
animations.put(2,new Animatable.AnimationPayload(400,1050,Animation.INDEFINITE, true));
|
||||
animations.put(3,new Animatable.AnimationPayload(400,1954,Animation.INDEFINITE, true));
|
||||
animations.put(4,new Animatable.AnimationPayload(400,1746,Animation.INDEFINITE, true));
|
||||
animations.put(5,new Animatable.AnimationPayload(950,1082,Animation.INDEFINITE, true));
|
||||
animations.put(6,new Animatable.AnimationPayload(800,2060,Animation.INDEFINITE, true));
|
||||
DeviceImgInstructionPane instructionPane = new DeviceImgInstructionPane(WindowManager.getContentHeight() + 30, WindowManager.getContentHeight() - 10, text, images, animations);
|
||||
//instructionPane.setOverlayLen(WindowManager.requireOverlayPane(), 0.6);
|
||||
|
||||
IDClickReceiver receiver = instructionPane.getIdClickReceiver();
|
||||
WindowManager.setMainContent(instructionPane, false);
|
||||
if (search) {
|
||||
DeviceManager.addMessageReceiver(receiver);
|
||||
}
|
||||
int message = CommonsMessages.NOOP;
|
||||
int exitcode = 0;
|
||||
while (message < 0){
|
||||
exitcode = 0;
|
||||
if (device != null) {
|
||||
if (Device.Status.DEVICE.equals(device.getStatus()) || Device.Status.UNAUTHORIZED.equals(device.getStatus())) {
|
||||
exitcode = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (message == CommonsMessages.NEW_DEVICE && !DeviceManager.getDevices().isEmpty()){
|
||||
Device d = DeviceManager.getFirstDevice();
|
||||
if (d != null && (Device.Status.DEVICE.equals(d.getStatus()) || Device.Status.UNAUTHORIZED.equals(d.getStatus()))) {
|
||||
exitcode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
message = instructionPane.waitClick();
|
||||
}
|
||||
DeviceManager.removeMessageReceiver(receiver);
|
||||
WindowManager.removeTopContent();
|
||||
return exitcode;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -182,34 +182,7 @@ public class ActionsStatic {
|
||||
};
|
||||
}
|
||||
|
||||
public static RunnableMessage HOWTO_GO_RECOVERY(){
|
||||
return () -> {
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.OK_UNDERSTAND);
|
||||
SidePane sidePane = new SidePane();
|
||||
DeviceRecoveryView deviceRecoveryView = new DeviceRecoveryView(DeviceView.DEVICE_18_9,640);
|
||||
deviceRecoveryView.animateSelectThird(2500);
|
||||
Text t = new Text("1) "+LRes.BTN_VOLUP_POW.toString()+"\n2) "+LRes.HT_RECOVERY_TEXT_1.toString());
|
||||
|
||||
t.setWrappingWidth(400);
|
||||
t.setFont(Font.font(15));
|
||||
sidePane.setLeft(t);
|
||||
Pane p = DeviceView.crop(deviceRecoveryView,410);
|
||||
|
||||
GuiUtils.debug(p);
|
||||
sidePane.setRight(GuiUtils.center(p));
|
||||
buttonPane.setContent(sidePane);
|
||||
WindowManager.setMainContent(buttonPane,false);
|
||||
DeviceManager.addMessageReceiver(buttonPane.getIdClickReceiver());
|
||||
int msg = NOOP;
|
||||
while (msg < 0 && (msg != CommonsMessages.NEW_DEVICE || DeviceManager.count(Device.Status.SIDELOAD) < 1)){
|
||||
//Log.debug(msg+" - "+DeviceManager.count(Device.Status.SIDELOAD));
|
||||
msg = buttonPane.waitClick();
|
||||
}
|
||||
DeviceManager.removeMessageReceiver(buttonPane.getIdClickReceiver());
|
||||
WindowManager.removeTopContent();
|
||||
return msg;
|
||||
};
|
||||
}
|
||||
|
||||
public static RunnableMessage REQUIRE_INTERNET_CONNECTION(){
|
||||
return () -> {
|
||||
@@ -260,6 +233,8 @@ public class ActionsStatic {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static RunnableMessage FIRST_DISCLAIMER() { return () -> {
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.DONT_AGREE.toString(),LRes.AGREE.toString());
|
||||
Text t2 = new Text(RawManager.getDisclaimer());
|
||||
@@ -280,7 +255,7 @@ public class ActionsStatic {
|
||||
DeviceView running = new DeviceView(DeviceView.DEVICE_18_9,height, Color.WHITE,null), recover = new DeviceView(DeviceView.DEVICE_18_9,height, Color.BLACK, null);
|
||||
running.getImagePane().setCursor(Cursor.HAND);
|
||||
recover.getImagePane().setCursor(Cursor.HAND);
|
||||
recover.setContent(DrawableManager.getPng(DrawableManager.FASTBOOT_LOGO));
|
||||
recover.setContent(DrawableManager.getPng(DrawableManager.FASTBOOT_LOGO),true);
|
||||
running.setContent(DrawableManager.getPng(DrawableManager.MIUI10));
|
||||
Button b1 = new CustomButton(LRes.CHOOSE);
|
||||
Button b2 = new CustomButton(LRes.CHOOSE);
|
||||
@@ -310,4 +285,6 @@ public class ActionsStatic {
|
||||
});
|
||||
return idClickReceiver.waitClick()%2;
|
||||
};}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.xiaomitool.v2.gui.visual.ToastPane;
|
||||
import com.xiaomitool.v2.gui.visual.VisiblePane;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.Pointer;
|
||||
import com.xiaomitool.v2.utility.SilentCompleteFuture;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
@@ -149,17 +150,30 @@ public class WindowManager {
|
||||
toastPane.toast(message);
|
||||
}
|
||||
public static Stage launchPopup(PopupWindow popupWindow){
|
||||
Pointer pointer = new Pointer();
|
||||
PopupController controller = new PopupController(popupWindow);
|
||||
Stage stage = launchWindow(FRAME_POPUP,controller,null,pointer);
|
||||
Parent p = stage.getScene().getRoot();
|
||||
StackPane mainPane = (StackPane) p;
|
||||
((Pane) pointer.pointed).setMinSize(popupWindow.getWidth(),popupWindow.getHeight());
|
||||
SilentCompleteFuture<Stage> future = new SilentCompleteFuture<>();
|
||||
|
||||
stage.setTitle(DEFAULT_TITLE);
|
||||
stage.sizeToScene();
|
||||
centerStage(stage);
|
||||
return stage;
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pointer pointer = new Pointer();
|
||||
PopupController controller = new PopupController(popupWindow);
|
||||
Stage stage = launchWindow(FRAME_POPUP,controller,null,pointer);
|
||||
Parent p = stage.getScene().getRoot();
|
||||
StackPane mainPane = (StackPane) p;
|
||||
((Pane) pointer.pointed).setMinSize(popupWindow.getWidth(),popupWindow.getHeight());
|
||||
|
||||
stage.setTitle(DEFAULT_TITLE);
|
||||
stage.sizeToScene();
|
||||
centerStage(stage);
|
||||
future.complete(stage);
|
||||
}
|
||||
};
|
||||
if (Platform.isFxApplicationThread()){
|
||||
runnable.run();
|
||||
} else {
|
||||
Platform.runLater(runnable);
|
||||
}
|
||||
return future.getSilently();
|
||||
|
||||
}
|
||||
private static Stage launchWindow(String fxml, DefaultController controller, Stage primaryStage){
|
||||
@@ -268,4 +282,8 @@ public class WindowManager {
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public static OverlayPane requireOverlayPane() {
|
||||
return mainOverlay;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,32 @@ package com.xiaomitool.v2.gui.deviceView;
|
||||
public interface Animatable {
|
||||
|
||||
public void animate(int times, long duration);
|
||||
|
||||
|
||||
public static class AnimationPayload {
|
||||
private double x,y;
|
||||
private int times;
|
||||
private boolean unique;
|
||||
public AnimationPayload(double x, double y, int times, boolean unique){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.times = times;
|
||||
this.unique = unique;
|
||||
}
|
||||
public double getX(){
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getTimes() {
|
||||
return times;
|
||||
}
|
||||
|
||||
public boolean isUnique() {
|
||||
return unique;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.xiaomitool.v2.gui.deviceView;
|
||||
|
||||
import com.xiaomitool.v2.utility.RunnableWithArg;
|
||||
|
||||
public abstract class AnimatableDeviceView extends DeviceView implements Animatable {
|
||||
|
||||
public AnimatableDeviceView(DeviceImage deviceImage, double wantedHeight) {
|
||||
super(deviceImage, wantedHeight);
|
||||
}
|
||||
|
||||
private RunnableWithArg animationCallback;
|
||||
public void setAnimationCallback(RunnableWithArg animationCallback){
|
||||
this.animationCallback = animationCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animate(int times, long duration) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i<times; ++i) {
|
||||
try {
|
||||
int step = 0;
|
||||
while (animate(step)) {
|
||||
if (animationCallback != null) {
|
||||
animationCallback.run(step);
|
||||
}
|
||||
step++;
|
||||
}
|
||||
Thread.sleep(duration);
|
||||
} catch (InterruptedException e) {
|
||||
animationCallback.run(-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
}
|
||||
|
||||
public abstract boolean animate(int step) throws InterruptedException;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.gui.drawable.DrawableManager;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.utils.NumberUtils;
|
||||
import javafx.scene.effect.BlendMode;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
@@ -13,18 +14,18 @@ import javafx.scene.shape.Rectangle;
|
||||
|
||||
public class DeviceRecoveryView extends DeviceView implements Animatable {
|
||||
private Rectangle selectRectangle;
|
||||
private ImageView recoveryImage = new ImageView(new Image(DrawableManager.getPng("recovery").toString())), pcsuiteImage = new ImageView(new Image(DrawableManager.getPng("pcsuiteicon").toString()));
|
||||
private Image recoveryImage = new Image(DrawableManager.getPng("recovery").toString()), pcsuiteImage = new Image(DrawableManager.getPng("pcsuiteicon").toString());
|
||||
public DeviceRecoveryView(DeviceImage deviceImage, double wantedHeight) {
|
||||
super(deviceImage, wantedHeight, Color.BLACK, null);
|
||||
|
||||
this.setContent(recoveryImage);
|
||||
selectOption(1);
|
||||
// this.setContent(recoveryImage,true);
|
||||
selectOption(0);
|
||||
//pcsuiteImage.setViewport(new Rectangle2D(0,-1*(deviceImage.getInnerHeight()-pcsuiteImage.getImage().getHeight())/2,pcsuiteImage.getImage().getWidth(), deviceImage.getInnerHeight()));
|
||||
|
||||
}
|
||||
|
||||
private Rectangle buildSelectRectangle(){
|
||||
Rectangle rectangle = new Rectangle(152*scaleRatio,736*scaleRatio,776*scaleRatio,126*scaleRatio);
|
||||
Rectangle rectangle = new Rectangle(152*scaleRatio,(736)*contentScaleRatio+NumberUtils.double2int(imageOffsetY),776*scaleRatio,126*scaleRatio);
|
||||
rectangle.setFill(Color.rgb(51,180, 255));
|
||||
rectangle.setBlendMode(BlendMode.ADD);
|
||||
rectangle.setArcWidth(6);
|
||||
@@ -39,16 +40,18 @@ public class DeviceRecoveryView extends DeviceView implements Animatable {
|
||||
}
|
||||
try {
|
||||
imageWrapPane.getChildren().add(selectRectangle);
|
||||
|
||||
} catch (Throwable t){
|
||||
Log.debug("Rectangle already present");
|
||||
}
|
||||
Log.debug("Layout y: "+(161*index)*scaleRatio);
|
||||
selectRectangle.setLayoutY((161*index)*scaleRatio);
|
||||
double layoutY = NumberUtils.double2int((736+161*index)*scaleRatio)+NumberUtils.double2int(imageOffsetY);
|
||||
Log.debug("Layout y: "+layoutY);
|
||||
selectRectangle.setLayoutY(layoutY);
|
||||
}
|
||||
|
||||
public void animateSelectThird(long duration){
|
||||
DeviceRecoveryView view = this;
|
||||
setContent(recoveryImage);
|
||||
setContent(recoveryImage, true);
|
||||
this.selectOption(0);
|
||||
this.setClickVolumeDown(1).setOnFinished(event -> {
|
||||
selectOption(1);
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.xiaomitool.v2.gui.deviceView;
|
||||
|
||||
import com.mortennobel.imagescaling.AdvancedResizeOp;
|
||||
import com.mortennobel.imagescaling.MultiStepRescaleOp;
|
||||
import com.mortennobel.imagescaling.ResampleFilters;
|
||||
import com.mortennobel.imagescaling.ResampleOp;
|
||||
import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.drawable.DrawableManager;
|
||||
import com.xiaomitool.v2.gui.visual.OverlayPane;
|
||||
@@ -7,9 +11,12 @@ import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.Nullable;
|
||||
import com.xiaomitool.v2.utility.Pointer;
|
||||
|
||||
import com.xiaomitool.v2.utility.utils.NumberUtils;
|
||||
import javafx.animation.*;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.embed.swing.SwingFXUtils;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
@@ -24,10 +31,16 @@ import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class DeviceView extends StackPane {
|
||||
private DeviceImage deviceImage;
|
||||
protected DeviceImage deviceImage;
|
||||
private ImageView deviceBorders, displayedImageView;
|
||||
protected double wantedHeight, scaleRatio;
|
||||
private Color background = Color.rgb(49, 53, 57), innerShadow = Color.BLACK;
|
||||
@@ -93,6 +106,7 @@ public class DeviceView extends StackPane {
|
||||
super.getChildren().add(containerPane);
|
||||
|
||||
}
|
||||
protected double contentScaleRatio;
|
||||
public void setContent(ImageView image){
|
||||
setContent(image,false);
|
||||
}
|
||||
@@ -107,7 +121,7 @@ public class DeviceView extends StackPane {
|
||||
setContent(new Image(url.toString()));
|
||||
}
|
||||
public void setContent(URL url, boolean keepratio){
|
||||
setContent(new Image(url.toString(), keepratio));
|
||||
setContent(new Image(url.toString(), false),keepratio);
|
||||
}
|
||||
public double getOuterAspectRatio(){
|
||||
return deviceImage.getOuterHeight()/deviceImage.getOuterWidth();
|
||||
@@ -115,49 +129,147 @@ public class DeviceView extends StackPane {
|
||||
public double getInnerAspectRatio(){
|
||||
return deviceImage.getInnerHeight()/deviceImage.getInnerWidth();
|
||||
}
|
||||
|
||||
public void setContent(ImageView image, boolean keepRatio) {
|
||||
|
||||
|
||||
image.setPreserveRatio(true);
|
||||
displayedImage = image.getImage();
|
||||
if (keepRatio){
|
||||
image.setViewport(new Rectangle2D(0,-1*(deviceImage.getInnerHeight()-displayedImage.getHeight())/2,displayedImage.getWidth(), deviceImage.getInnerHeight()));
|
||||
private double getInnerHeight(){
|
||||
return this.deviceImage.getInnerHeight()*this.scaleRatio;
|
||||
}
|
||||
//image.setSmooth(true);
|
||||
double offsetX = 0, offsetY =0 , height, width;
|
||||
if (image.getViewport() != null){
|
||||
height = image.getViewport().getHeight();
|
||||
width = image.getViewport().getWidth();
|
||||
offsetX = image.getViewport().getMinX();
|
||||
offsetY = image.getViewport().getMinY();
|
||||
private double getInnerWidth(){
|
||||
return this.deviceImage.getInnerWidth()*this.scaleRatio;
|
||||
}
|
||||
|
||||
protected double imageOffsetX, imageOffsetY;
|
||||
protected boolean keepRatio;
|
||||
public void setContent(ImageView image, boolean keepRatio) {
|
||||
this.keepRatio = keepRatio;
|
||||
displayedImage = image.getImage();
|
||||
Log.debug("Original image size: "+displayedImage.getHeight()+"x"+displayedImage.getWidth());
|
||||
double origImgRatio = displayedImage.getHeight()/displayedImage.getWidth();
|
||||
int resizeWidth, resizeHeight;
|
||||
Rectangle2D viewport;
|
||||
if (origImgRatio < this.getInnerAspectRatio()){
|
||||
resizeWidth = NumberUtils.double2int(this.getInnerWidth());
|
||||
resizeHeight = NumberUtils.double2int(keepRatio ? resizeWidth*origImgRatio : this.getInnerHeight());
|
||||
imageOffsetY = keepRatio ? (this.getInnerHeight()-resizeHeight)/2 : 0;
|
||||
imageOffsetX = 0;
|
||||
viewport = keepRatio ? new Rectangle2D(0,-1*imageOffsetY,this.getInnerWidth(), this.getInnerHeight()) : null;
|
||||
|
||||
} else {
|
||||
resizeHeight = NumberUtils.double2int(this.getInnerHeight());
|
||||
resizeWidth = NumberUtils.double2int(keepRatio ? resizeHeight/origImgRatio : this.getInnerWidth());
|
||||
imageOffsetX = keepRatio ? (this.getInnerWidth()-resizeWidth)/2 : 0;
|
||||
imageOffsetY = 0;
|
||||
viewport = keepRatio ? new Rectangle2D(-1*imageOffsetX,0,this.getInnerWidth(), this.getInnerHeight()) : null;
|
||||
}
|
||||
Log.debug("Viewport: "+viewport);
|
||||
Log.debug("iOX = "+imageOffsetX+", iOY = "+imageOffsetY);
|
||||
contentScaleRatio = ((double) resizeHeight)/displayedImage.getHeight();
|
||||
Log.debug("RSW: "+resizeWidth+", RSH: "+resizeHeight+", CSR: "+contentScaleRatio+", DIH:"+displayedImage.getHeight());
|
||||
BufferedImage srcImg = SwingFXUtils.fromFXImage(image.getImage(), null);
|
||||
BufferedImage img = new BufferedImage(resizeWidth, resizeHeight, srcImg.getType());
|
||||
if (true){
|
||||
MultiStepRescaleOp resampleOp = new MultiStepRescaleOp(resizeWidth, resizeHeight, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||
resampleOp.doFilter(srcImg, img, resizeWidth, resizeHeight);
|
||||
} else {
|
||||
ResampleOp resampleOp = new ResampleOp(resizeWidth, resizeHeight);
|
||||
resampleOp.setFilter(ResampleFilters.getBiCubicFilter());
|
||||
resampleOp.doFilter(srcImg, img, resizeWidth, resizeHeight);
|
||||
}
|
||||
Log.debug("Raw resized img: "+img.getHeight()+"x"+img.getWidth());
|
||||
|
||||
//
|
||||
|
||||
Image resizedImage = SwingFXUtils.toFXImage(img, null);
|
||||
image.setImage(resizedImage);
|
||||
if (viewport != null){
|
||||
image.setViewport(viewport);
|
||||
}
|
||||
image.setFitWidth(NumberUtils.double2int(this.getInnerWidth()));
|
||||
image.setFitHeight(NumberUtils.double2int(this.getInnerHeight()));
|
||||
Log.debug("Result: "+image.getFitHeight()+"x"+image.getFitWidth()+" -img-> "+image.getImage().getHeight()+"x"+image.getImage().getWidth());
|
||||
|
||||
contentPane.getChildren().clear();
|
||||
|
||||
displayedImageView = image;
|
||||
|
||||
imageWrapPane = new Pane(image);
|
||||
|
||||
|
||||
contentPane.getChildren().clear();
|
||||
contentPane.getChildren().add(GuiUtils.center(imageWrapPane));
|
||||
|
||||
|
||||
/* //image.setSmooth(true);
|
||||
double offsetX = 0, offsetY =0 , height, width;
|
||||
image.setPreserveRatio(true);
|
||||
if (keepRatio){
|
||||
|
||||
Log.debug("KEEEPRATIIOOO");
|
||||
height = deviceImage.getInnerHeight();
|
||||
width = displayedImage.getWidth();
|
||||
|
||||
offsetX = 0;
|
||||
offsetY = -1*(deviceImage.getInnerHeight()-displayedImage.getHeight())/2;
|
||||
image.setViewport(new Rectangle2D(offsetX,offsetY,width,height));
|
||||
} else {
|
||||
Log.debug("DONTT KEEEPRATIIOOO");
|
||||
height = displayedImage.getHeight();
|
||||
Log.debug("Height: "+displayedImage.getHeight());
|
||||
width = displayedImage.getWidth();
|
||||
}
|
||||
Log.debug("Width: "+width+", height: "+height);
|
||||
double setHeight = height-offsetY;
|
||||
double setWidth = width-offsetX;
|
||||
double innerRatio = deviceImage.getInnerHeight()/deviceImage.getInnerWidth();
|
||||
double imgRatio = setHeight/setWidth;
|
||||
double wantedH = -1, wantedW = -1;
|
||||
if (innerRatio < imgRatio){
|
||||
Log.debug("Image is taller than frame: height -> "+setHeight);
|
||||
double h = Double.min(setHeight, deviceImage.getInnerHeight()*scaleRatio);
|
||||
wantedH = Double.min(setHeight, deviceImage.getInnerHeight()*scaleRatio);
|
||||
//h = keepRatio ? Double.min(h, displayedImage.getHeight()) : h;
|
||||
image.setFitHeight(h);
|
||||
Log.debug("Wanted height: "+wantedH);
|
||||
|
||||
} else {
|
||||
double w = Double.min(setWidth, deviceImage.getInnerWidth()*scaleRatio);
|
||||
wantedW = Double.min(setWidth, deviceImage.getInnerWidth()*scaleRatio);
|
||||
//w = keepRatio ? Double.min(w, displayedImage.getWidth()) : w;
|
||||
Log.debug("Image is wider than frame: width -> "+(deviceImage.getInnerWidth()*scaleRatio));
|
||||
image.setFitWidth(w);
|
||||
Log.debug("Wanted width: "+wantedW);
|
||||
|
||||
}
|
||||
int dstH = new Double(wantedH).intValue(), dstW = new Double(wantedW).intValue();
|
||||
if (dstH < 0){
|
||||
Log.debug(keepRatio);
|
||||
Log.debug("DstH: "+dstH+", DstW: "+dstW);
|
||||
Log.debug(displayedImage.impl_getUrl());
|
||||
Log.debug("Dst ration: "+(displayedImage.getHeight()/displayedImage.getWidth()));
|
||||
dstH = new Double(keepRatio ? (dstW*displayedImage.getHeight()/displayedImage.getWidth()) : dstW*getInnerAspectRatio()).intValue();
|
||||
} else if (dstW <0){
|
||||
Log.debug("DstH: "+dstH+", DstW: "+dstW);
|
||||
Log.debug(displayedImage.impl_getUrl());
|
||||
Log.debug("Dst ration: "+(displayedImage.getWidth()/displayedImage.getHeight()));
|
||||
dstW = new Double(keepRatio ? (dstH*displayedImage.getWidth()/displayedImage.getHeight()) : dstH/getInnerAspectRatio()).intValue();
|
||||
}
|
||||
Log.debug("DstH: "+dstH+", DstW: "+dstW);
|
||||
|
||||
BufferedImage srcImg = SwingFXUtils.fromFXImage(image.getImage(), null);
|
||||
BufferedImage img = new BufferedImage(dstW, dstH, srcImg.getType());
|
||||
new ResampleOp(dstW, dstH).doFilter(srcImg, img, dstW, dstH);
|
||||
Image dstImg = SwingFXUtils.toFXImage(img, null);
|
||||
image.setSmooth(false);
|
||||
image.setImage(dstImg);
|
||||
|
||||
|
||||
if (wantedW >= 0){
|
||||
image.setFitWidth(wantedW);
|
||||
}
|
||||
if (wantedH >= 0){
|
||||
image.setFitHeight(wantedH);
|
||||
}
|
||||
//image.setFitHeight(wantedHeight * deviceImage.getInnerHeight() / deviceImage.getOuterHeight());
|
||||
contentPane.getChildren().clear();
|
||||
|
||||
displayedImageView = image;
|
||||
|
||||
imageWrapPane = new Pane(image);
|
||||
contentPane.getChildren().add(GuiUtils.center(imageWrapPane));
|
||||
contentPane.getChildren().add(GuiUtils.center(imageWrapPane));*/
|
||||
|
||||
}
|
||||
|
||||
@@ -255,7 +367,7 @@ public class DeviceView extends StackPane {
|
||||
double centerY = (pos.top + pos.height / 2) ;
|
||||
rectangle.setFill(Color.RED);
|
||||
containerPane.getChildren().add(rectangle);
|
||||
Transition transition = buildCircleTransition(centerX,centerY,times,false);
|
||||
Transition transition = buildCircleTransition(centerX,centerY,times,false,false);
|
||||
transition.statusProperty().addListener((observable, oldValue, newValue) -> {
|
||||
Log.debug(oldValue.toString()+" -> "+newValue.toString());
|
||||
if (Animation.Status.STOPPED.equals(newValue)){
|
||||
@@ -272,15 +384,52 @@ public class DeviceView extends StackPane {
|
||||
}
|
||||
|
||||
public Transition buildCircleTransition(double x, double y, int times){
|
||||
return buildCircleTransition(x,y,times,true);
|
||||
return buildCircleTransition(x,y,times,true, true);
|
||||
}
|
||||
|
||||
public Transition buildCircleTransition(double x, double y, int times, boolean addBorder){
|
||||
Circle circle = new Circle(x*scaleRatio+(addBorder ? deviceImage.getLeftOffset()*scaleRatio : 0), y*scaleRatio+(addBorder ? deviceImage.getTopOffset() * scaleRatio : 0), wantedHeight / 12);
|
||||
private final ConcurrentLinkedQueue<Transition> circlesAnimation = new ConcurrentLinkedQueue<>();
|
||||
public void removeCircleAnimation(){
|
||||
Log.debug("Clearing anims");
|
||||
synchronized (circlesAnimation) {
|
||||
for (Transition transition : circlesAnimation) {
|
||||
Log.debug("Clearing trans: "+transition.toString());
|
||||
transition.stop();
|
||||
}
|
||||
circlesAnimation.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public Transition buildCircleTransition(double x, double y, int times, boolean addBorder, boolean unique){
|
||||
if (!Platform.isFxApplicationThread()){
|
||||
CompletableFuture<Transition> future = new CompletableFuture<>();
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
|
||||
future.complete(buildCircleTransition(x,y,times,addBorder, unique));
|
||||
}
|
||||
});
|
||||
try {
|
||||
return future.get();
|
||||
} catch (InterruptedException e) {
|
||||
removeCircleAnimation();
|
||||
return null;
|
||||
} catch (ExecutionException e) {
|
||||
removeCircleAnimation();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if(unique){
|
||||
removeCircleAnimation();
|
||||
}
|
||||
Circle circle = new Circle(x*scaleRatio+(addBorder ? deviceImage.getLeftOffset()*scaleRatio+imageOffsetX : 0), y*scaleRatio+(addBorder ? imageOffsetY+deviceImage.getTopOffset() * scaleRatio : 0), wantedHeight / 12);
|
||||
circle.setStroke(Color.RED);
|
||||
circle.setStrokeWidth(3);
|
||||
circle.setFill(Color.TRANSPARENT);
|
||||
circle.setVisible(false);
|
||||
circle.setOpacity(0);
|
||||
circle.setMouseTransparent(true);
|
||||
|
||||
Transition transition = getCircleTransition(circle, times);
|
||||
containerPane.getChildren().add(circle);
|
||||
@@ -290,13 +439,16 @@ public class DeviceView extends StackPane {
|
||||
Log.debug(oldValue.toString()+" -> "+newValue.toString());
|
||||
if (Animation.Status.STOPPED.equals(newValue)){
|
||||
circle.setVisible(false);
|
||||
containerPane.getChildren().removeAll(circle);
|
||||
containerPane.getChildren().remove(circle);
|
||||
} else if (Animation.Status.RUNNING.equals(newValue)){
|
||||
circle.setVisible(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
transition.play();
|
||||
synchronized (circlesAnimation){
|
||||
this.circlesAnimation.add(transition);
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
|
||||
|
Antes Largura: | Altura: | Tamanho: 154 KiB Depois Largura: | Altura: | Tamanho: 2.1 MiB |
|
Depois Largura: | Altura: | Tamanho: 6.1 KiB |
|
Antes Largura: | Altura: | Tamanho: 11 KiB Depois Largura: | Altura: | Tamanho: 15 KiB |
|
Depois Largura: | Altura: | Tamanho: 2.9 MiB |
|
Depois Largura: | Altura: | Tamanho: 124 KiB |
|
Depois Largura: | Altura: | Tamanho: 171 KiB |
|
Depois Largura: | Altura: | Tamanho: 117 KiB |
|
Depois Largura: | Altura: | Tamanho: 97 KiB |
|
Depois Largura: | Altura: | Tamanho: 158 KiB |
|
Depois Largura: | Altura: | Tamanho: 157 KiB |
@@ -0,0 +1,149 @@
|
||||
package com.xiaomitool.v2.gui.visual;
|
||||
|
||||
|
||||
|
||||
import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.deviceView.Animatable;
|
||||
import com.xiaomitool.v2.gui.deviceView.AnimatableDeviceView;
|
||||
import com.xiaomitool.v2.gui.deviceView.DeviceView;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.RunnableWithArg;
|
||||
import javafx.animation.Transition;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextAlignment;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class DeviceImgInstructionPane extends SidePane {
|
||||
|
||||
|
||||
private String[] texts;
|
||||
private Image[] images;
|
||||
private HashMap<Integer, Animatable.AnimationPayload> animations;
|
||||
|
||||
public DeviceImgInstructionPane(double wantedHeight, double maxHeight, String[] texts, Image[] images, HashMap<Integer, Animatable.AnimationPayload> animations){
|
||||
this.texts = texts;
|
||||
this.images = images;
|
||||
this.animations = animations;
|
||||
build(wantedHeight,maxHeight);
|
||||
}
|
||||
|
||||
|
||||
private int index = 0;
|
||||
private Button prevButton, nextButton;
|
||||
private Text instructionText;
|
||||
private AnimatableDeviceView deviceView;
|
||||
private ButtonPane closeButtonPane;
|
||||
private Transition currentAnimation = null;
|
||||
private void build(double wantedHeight, double maxHeight){
|
||||
if (texts == null || images == null || texts.length != images.length || texts.length == 0){
|
||||
throw new IllegalArgumentException("Please, pass not null, not empty arrays with same num of elements");
|
||||
}
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.PREV_STEP, LRes.NEXT_STEP);
|
||||
closeButtonPane = new ButtonPane(LRes.OK_FINISHED);
|
||||
List<CustomButton> btns = buttonPane.getButtons();
|
||||
prevButton = btns.get(0);
|
||||
nextButton = btns.get(1);
|
||||
prevButton.setDisable(true);
|
||||
instructionText = new Text();
|
||||
instructionText.setWrappingWidth(400);
|
||||
instructionText.setFont(Font.font(15));
|
||||
instructionText.setTextAlignment(TextAlignment.CENTER);
|
||||
buttonPane.setContent(instructionText);
|
||||
deviceView = new AnimatableDeviceView(DeviceView.DEVICE_18_9, wantedHeight) {
|
||||
@Override
|
||||
public boolean animate(int step) throws InterruptedException {
|
||||
if (animations != null) {
|
||||
Animatable.AnimationPayload payload = animations.get(step);
|
||||
if (payload != null) {
|
||||
currentAnimation = this.buildCircleTransition(payload.getX(), payload.getY(), payload.getTimes(), true, payload.isUnique());
|
||||
} else {
|
||||
deviceView.removeCircleAnimation();
|
||||
}
|
||||
}
|
||||
return index < texts.length -1;
|
||||
}
|
||||
};
|
||||
deviceView.setContent(images[index]);
|
||||
buttonPane.getIdClickReceiver().addListener(new RunnableWithArg() {
|
||||
@Override
|
||||
public void run(Object arg) {
|
||||
int click = (int) arg;
|
||||
if (click == 0){
|
||||
index--;
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
loadStep();
|
||||
}
|
||||
});
|
||||
closeButtonPane.setContent(buttonPane);
|
||||
StackPane stackPane = new StackPane(closeButtonPane);
|
||||
stackPane.setPadding(new Insets(20,0,30,20));
|
||||
loadStep();
|
||||
this.setLeft(stackPane);
|
||||
this.setRight(GuiUtils.center(DeviceView.crop(deviceView, wantedHeight, wantedHeight > maxHeight ? (wantedHeight - maxHeight)/2 : 0)));
|
||||
}
|
||||
|
||||
public void animate() throws InterruptedException {
|
||||
deviceView.animate(index);
|
||||
}
|
||||
|
||||
public void setOverlayLen(OverlayPane pane, double zoomRatio){
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
deviceView.setLenOverlay(pane,300, zoomRatio);
|
||||
}
|
||||
};
|
||||
if (!Platform.isFxApplicationThread()){
|
||||
Platform.runLater(runnable);
|
||||
} else {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void loadStep(){
|
||||
Image toLoadImg = images[index];
|
||||
String toLoadText = LRes.STEP.toString()+" ["+(index+1)+"/"+(texts.length)+"]:\n"+texts[index];
|
||||
|
||||
if (index == 0){
|
||||
prevButton.setDisable(true);
|
||||
} else {
|
||||
prevButton.setDisable(false);
|
||||
}
|
||||
if (index == texts.length -1){
|
||||
nextButton.setDisable(true);
|
||||
} else{
|
||||
nextButton.setDisable(false);
|
||||
}
|
||||
instructionText.setText(toLoadText);
|
||||
deviceView.setContent(toLoadImg);
|
||||
try {
|
||||
animate();
|
||||
} catch (InterruptedException e) {
|
||||
Log.warn("Animation error: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public int waitClick() throws InterruptedException {
|
||||
return this.closeButtonPane.waitClick();
|
||||
}
|
||||
|
||||
public IDClickReceiver getIdClickReceiver(){
|
||||
return this.closeButtonPane.getIdClickReceiver();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -2,13 +2,23 @@ package com.xiaomitool.v2.gui.visual;
|
||||
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.MessageReceiver;
|
||||
import com.xiaomitool.v2.utility.RunnableWithArg;
|
||||
import com.xiaomitool.v2.utility.WaitSemaphore;
|
||||
import javafx.scene.Node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class IDClickReceiver implements MessageReceiver {
|
||||
|
||||
private final List<RunnableWithArg> listeners = Collections.synchronizedList(new ArrayList<>());
|
||||
public void addListener(RunnableWithArg args){
|
||||
synchronized (listeners) {
|
||||
this.listeners.add(args);
|
||||
}
|
||||
}
|
||||
|
||||
private static class IDNode {
|
||||
public int id;
|
||||
public Node node;
|
||||
@@ -49,9 +59,20 @@ public class IDClickReceiver implements MessageReceiver {
|
||||
return lastClickID;
|
||||
}
|
||||
public void message(int message){
|
||||
synchronized (listeners){
|
||||
for (RunnableWithArg runnable : listeners){
|
||||
runnable.run(message);
|
||||
}
|
||||
}
|
||||
lastClickID =message;
|
||||
semaphore.increase();
|
||||
}
|
||||
|
||||
public boolean removeListener(RunnableWithArg arg){
|
||||
return this.listeners.remove(arg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.xiaomitool.v2.gui.visual;
|
||||
|
||||
import com.sun.glass.ui.Window;
|
||||
|
||||
import com.xiaomitool.v2.engine.actions.ActionsStatic;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
@@ -67,7 +67,7 @@ public class InstallPane extends StackPane {
|
||||
stackTrace = StrUtils.firstNLines(stackTrace,5);
|
||||
ErrorPane errorPane = new ErrorPane(LRes.CANCEL, LRes.STEP_BACK, LRes.TRY_AGAIN);
|
||||
errorPane.setTitle(LRes.PROCEDURE_EXC_TITLE.toString(), Color.rgb(128,0,0));
|
||||
errorPane.setText(LRes.PROCEDURE_EXC_TEXT.toString()+"\n\n"+LRes.PROCEDURE_EXC_DETAILS.toString(exception.getCode().toString()));
|
||||
errorPane.setText(LRes.PROCEDURE_EXC_TEXT.toString(LRes.PROCEDURE_EXC_DETAILS.toString(exception.getCode().toString(), exception.getMessage())+"\n",LRes.TRY_AGAIN, LRes.STEP_BACK, LRes.CANCEL));
|
||||
Text t2 = new Text(LRes.PROCEDURE_EXC_ADV_DETAILS.toString()+": "+exception.getMessage()+"\n"+stackTrace+(stackTrace.length() != len ? "\n..." : ""));
|
||||
t2.setTextAlignment(TextAlignment.CENTER);
|
||||
t2.setWrappingWidth(WindowManager.getContentWidth()-100);
|
||||
@@ -83,16 +83,6 @@ public class InstallPane extends StackPane {
|
||||
}
|
||||
WindowManager.removeTopContent();
|
||||
if (msg == 0){
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActionsStatic.MOD_CHOOSE_SCREEN().run();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
this.sendCommand(Command.ABORT);
|
||||
} else if (msg == 1){
|
||||
this.sendCommand(Command.UPLEVEL);
|
||||
|
||||
@@ -38,7 +38,7 @@ public enum LRes {
|
||||
SELECTED_DEVICE("Selected device: %s"),
|
||||
TRY_AGAIN("Try again"),
|
||||
DEVICE_NOT_CONNECTED("It seems your device is not connected. Please make sure your device is on, connected to your pc and with usb debugging enabled"),
|
||||
AUTH_DEVICE_TEXT("Your device is offline or not authorized. Please authorize your device by clicking on the popup window that is displayed on its screen."),
|
||||
AUTH_DEVICE_TEXT("Your device is offline or not authorized. Please authorize your device by clicking on the popup window that is displayed on its screen.\nIf the device is in recovery mode or doesn't have the popup, try unplugging and pluggin back in the cable"),
|
||||
YES("Yes"),
|
||||
NO("No"),
|
||||
IRRELEVANT("Irrilevant"),
|
||||
@@ -78,7 +78,7 @@ public enum LRes {
|
||||
PARTITION_FORMATTED("Partition formatted"),
|
||||
FETCHING_RECOVERY_INFO("Retrieving recovery information"),
|
||||
DONATE("Make a donation"),
|
||||
DONATE_DONT("Don't give a ****"),
|
||||
DONATE_DONT("Make the dev bankrupt"),
|
||||
DONATE_TEXT("This tool has been developed thanks to the users donations.\nThe developer of this tool isn't paid for his work and he is paying for services with his pocket money, leaving this tool free.\nIf you want to show your gratitude to him or support this project you can still offer him a beer by making a donation.\n\nWould you like to make a donation?"),
|
||||
INSTALL_SUCCESS("Installation completed succesfully!"),
|
||||
DOWNLOADING_ROM_FILE("Downloading rom file..."),
|
||||
@@ -102,8 +102,8 @@ public enum LRes {
|
||||
LOGIN_CANCELED("Login canceled or failed"),
|
||||
LOGIN_SUCCESS("Logged in succesfully"),
|
||||
PROCEDURE_EXC_TITLE("Procedure error occurred"),
|
||||
PROCEDURE_EXC_TEXT("There was an error during the installation producedure.\nYou can choose between trying again starting from the failed step, or step back to a previous step and trying again the procedure, or cancel the operation and abort the installation process."),
|
||||
PROCEDURE_EXC_DETAILS("Error details:\nError code: %s"),
|
||||
PROCEDURE_EXC_TEXT("There was an error during the installation producedure.\n%s\nPress \"%s\" to try again the failed procedure.\nPress \"%s\" to go a step back and try again the entire latest step\nPress \"%s\" to cancel the procedure and abort the installation process"),
|
||||
PROCEDURE_EXC_DETAILS("Error type: %s\nError description: %s"),
|
||||
PROCEDURE_EXC_ADV_DETAILS("Advanced error details"),
|
||||
CANCEL("Cancel"),
|
||||
STEP_BACK("Step back"),
|
||||
@@ -161,17 +161,18 @@ public enum LRes {
|
||||
REBOOT_RECOVERY_FAILED("Your device should enter recovery mode, but it seems it failed to do that or is not recognized or not connected.\nPlease hold the volume+ and power button to reboot it to recovery mode.\n\nFail cause: %s"),
|
||||
REBOOT_BOOTLOADER_FAILED("Your device should enter fastboot mode, but it seems it failed to do that or is not recognized or not connected.\nPlease hold the volume- and power button to reboot it to fastboot mode.\n\nFail cause: %s"),
|
||||
REBOOT_STOCKRECOVERY_FAILED("Your device should enter stock recovery mode, but it seems it failed to do that or is not recognized or not connected.\nPlease hold the volume+ and power button to reboot it to stock recovery mode.\n\nFail cause: %s"),
|
||||
FLASHING_STUFF("Flashing %s..."),
|
||||
BOOTING_STUFF("Booting %s..."),
|
||||
FLASHING_STUFF("Flashing %s"),
|
||||
BOOTING_STUFF("Booting %s"),
|
||||
CREATING_DEST_DIR("Creating destination directory"),
|
||||
WAITING_DEVICE_ACTIVE("Waiting device active status"),
|
||||
WAITING_DEVICE_ACTIVE("Waiting for device %s connection"),
|
||||
SEARCHING_LATEST_FASTBOOT("Searching latest fastboot rom: %s"),
|
||||
CALCULATING_MD5("Calculating md5 hash of file"),
|
||||
SEARCHING_XIAOMIEU_ROM("Searching latest Xiaomi.eu rom: %s"),
|
||||
SEARCHING_LATEST_MAGISK("Searching latest magisk zip file"),
|
||||
VALIDATING_PKG_ROM("Trying to validate rom package with miui server"),
|
||||
OTA_REQUEST_RUN("Running ota request to miui server"),
|
||||
SEARCHING_LATEST_RECOVERY_ROM("Searching latest recovery rom: %s"),
|
||||
SEARCHING_LATEST_OTA_ROM("Searching latest rom available through ota: %s"),
|
||||
REQUEST_OTA_INSTALLATION_TOKEN("Requesting ota installation token for rom: %s"),
|
||||
BACK_TO_CATEGORIES("Back to categories"),
|
||||
BACK_TO_CATEGORIES_TEXT("Go back and choose another category of installables"),
|
||||
STARTING_MIUI_SIDELOAD("Starting MIUI sideload procedure"),
|
||||
@@ -185,8 +186,47 @@ public enum LRes {
|
||||
ENABLE_USB_DEBUG_IF_NOT("Enable usb debugging (if not enabled)"),
|
||||
EXTRACTING_ROM_FILE("Extracting rom file..."),
|
||||
CHOOSE_PROCEDURE_CATEGORY("Please choose procedure category"),
|
||||
CHOOSE_PROCEDURE("Please choose which rom/procedure you want")
|
||||
CHOOSE_PROCEDURE("Please choose which rom/procedure you want"),
|
||||
ENTER_STOCK_RECOVERY_MODE("Your device is rebooting to stock recovery mode.\nYou should see this menu in a few seconds.\nPlease use the volume down button to move to the third option and then the power button to select it.\nThis will enable the required adb connection between the device and this pc."),
|
||||
SKIP("Skip"),
|
||||
NO_INTERNET_BEFORE_FETCH("No internet connection found!\n\nThis tool uses Internet connection to find automaticcaly the latest roms and mods that you can install on your device.\nWithout internet connection this feature will not work.\nYou should enable your internet connection to get the best experience out of this tool.\nChoose if you want to skip this feature or enable internet connection and press try again"),
|
||||
CONFIRM_INSTALLATION_START("You are about to start the installation procedure!\nThis is the last confirmation request before XiaoMiTool will do all of its things and manage your device with advanced procedures\n\nYou are going to lose all (or some part) of the personal data (photos, files, applications) on your device, so DO A BACKUP if you want to save them.\nBy pressing \"%s\" you are responsible of lost data, bricked devices and all the possible outcomes of the procedure\n"),
|
||||
NEXT_STEP("Next step"),
|
||||
PREV_STEP("Previous step"),
|
||||
HT_ENABLE_USB_1("Go the device setting by pressing the settings icon in the launcher"),
|
||||
HT_ENABLE_USB_2("Tap the \"About phone\" option and enter \"All specs\" menu"),
|
||||
HT_ENABLE_USB_3("Tap several (about ten) times the \"MIUI version\" entry in the menu until you get the message \"You are now a developer\""),
|
||||
HT_ENABLE_USB_4("Go back to the main settings menu and tap the \"Additional settings\" voice"),
|
||||
HT_ENABLE_USB_5("Scroll down and tap the \"Developer options\" menu option"),
|
||||
HT_ENABLE_USB_6("Scroll down and find the \"USB Debugging\" option"),
|
||||
HT_ENABLE_USB_7("Tap the toggle to enable the USB debugging and press \"OK\" to confirm"),
|
||||
OK_FINISHED("Ok, finished all"),
|
||||
WAITING_USB_ENABLE("Waiting for USB Debugging connection\nPlease enable the USB Debugging on your device and then press \"%s\"!"),
|
||||
STEP("Step"),
|
||||
CAN_TAKE_COUPLE_MIN("Please wait, it can take a couple of minutes"),
|
||||
UNL_UNKNOWN_ERROR("Unknown error: %d"),
|
||||
UNL_ERR_10000("10000:Request parameter error"),
|
||||
UNL_ERR_10001("10001:Signature verification failed"),
|
||||
UNL_ERR_10002("10002:The same IP request too often"),
|
||||
UNL_ERR_10003("10003:Internal server error"),
|
||||
UNL_ERR_10004("10004:Request has expired"),
|
||||
UNL_ERR_10005("10005:Invalid Nonce request"),
|
||||
UNL_ERR_10006("10006:Client version is too low"),
|
||||
UNL_ERR_20030("You have already unlocked a device recently.\nYou should wait at least 30 days from the first unlock to unlock another device"),
|
||||
UNL_ERR_20031("This device is not binded to your account.\nTurn on your device and bind your account to the device by going in MIUI's Settings > Developer options > Mi Unlock status."),
|
||||
UNL_ERR_20032("Failed to generate signature value required to unlock"),
|
||||
UNL_ERR_20033("User portrait scores too low or black"),
|
||||
UNL_ERR_20034("Current account cannot unlock this device"),
|
||||
UNL_ERR_20035("This tool is outdated, if you want to unlock your device then go to unlock.update.miui.com to download the latest version of MiUnlock"),
|
||||
UNL_ERR_20036("Your account is binded to this device for not enough time.\nYou have to wait %d days and %d hours before you can unlock this device"),
|
||||
UNL_ERR_20036_NOHOURS("You have to wait %d days and %d hours before you can unlock your device"),
|
||||
UNL_ERR_20037("Unlock number has reached the upper limit"),
|
||||
UNL_ERR_20041("Your account isn't associated with a phone number\nGo to account.xiaomi.com and associate it with your phone number"),
|
||||
UNLOCK_ERROR_TEXT("Failed to unlock your device, Xiaomi server returned error %d:\nError description: %s"),
|
||||
UNLOCK_CHECKING_ACCOUNT("Checking account unlock availability"),
|
||||
UNLOCK_CHECKING_DEVICE("Checking device unlock capability")
|
||||
;
|
||||
|
||||
private String text;
|
||||
|
||||
LRes(String defaultText){
|
||||
|
||||
@@ -36,7 +36,7 @@ public class Log {
|
||||
|
||||
public static void debug(Object arg){
|
||||
|
||||
log(PREFIX_DEBUG,arg);
|
||||
//log(PREFIX_DEBUG,arg);
|
||||
}
|
||||
public static void debugLine(){
|
||||
Log.debug("-----------------------------");
|
||||
|
||||
@@ -4,8 +4,10 @@ import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.adb.device.DeviceManager;
|
||||
import com.xiaomitool.v2.adb.device.DeviceProperties;
|
||||
import com.xiaomitool.v2.gui.visual.InstallPane;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.procedure.install.InstallException;
|
||||
import com.xiaomitool.v2.rom.Installable;
|
||||
import com.xiaomitool.v2.utility.utils.StrUtils;
|
||||
import javafx.scene.layout.Pane;
|
||||
|
||||
|
||||
@@ -137,10 +139,14 @@ public class ProcedureRunner extends GuiListener {
|
||||
private HashMap<String, Object> context = new HashMap<>();
|
||||
public void setContext(String key, Object value){
|
||||
context.put(key,value);
|
||||
Log.debug("Context var set: "+key+" -> "+StrUtils.str(value));
|
||||
}
|
||||
|
||||
public Object getContext(String key){
|
||||
return context.get(key);
|
||||
|
||||
Object res = context.get(key);
|
||||
Log.debug("Getting context var: "+key+" -> "+StrUtils.str(res));
|
||||
return res;
|
||||
}
|
||||
public Object requireContext(String key) throws InstallException {
|
||||
Object res = getContext(key);
|
||||
|
||||
@@ -5,9 +5,17 @@ import com.xiaomitool.v2.procedure.ProcedureRunner;
|
||||
import com.xiaomitool.v2.procedure.install.InstallException;
|
||||
|
||||
public abstract class RInstall {
|
||||
|
||||
private StackTraceElement[] creationStack;
|
||||
public RInstall(){
|
||||
creationStack = Thread.currentThread().getStackTrace();
|
||||
}
|
||||
|
||||
public abstract void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException;
|
||||
|
||||
void runInternal(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Log.debug("Running now procedure: "+this.toString(2));
|
||||
run(runner);
|
||||
}
|
||||
protected int flags;
|
||||
|
||||
public boolean hasFlag(int flag){
|
||||
@@ -26,4 +34,15 @@ public abstract class RInstall {
|
||||
return RNode.sequence(this, Procedures.runStackedProcedures());
|
||||
}
|
||||
|
||||
public String toString(int stackElements){
|
||||
stackElements+=3;
|
||||
stackElements = Integer.min(stackElements, creationStack.length);
|
||||
StringBuilder builder = new StringBuilder(creationStack[3].toString());
|
||||
for (int i = 4; i< stackElements; ++i){
|
||||
builder.append(" -> ");
|
||||
builder.append(creationStack[i].toString());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,10 @@ public abstract class RNode extends RInstall {
|
||||
this.type = type;
|
||||
this.chidren = chidren;
|
||||
}
|
||||
@Override
|
||||
void runInternal(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
run(runner);
|
||||
}
|
||||
|
||||
public static RNode sequence(RInstall... chidren){
|
||||
return new RNodeSequence(chidren);
|
||||
@@ -72,7 +76,7 @@ public abstract class RNode extends RInstall {
|
||||
for (RInstall install : chidren) {
|
||||
do {
|
||||
try {
|
||||
install.run(runner);
|
||||
install.runInternal(runner);
|
||||
break;
|
||||
} catch (InstallException e) {
|
||||
Log.debug("PROCEDURE EXC: "+e.getMessage());
|
||||
@@ -90,10 +94,19 @@ public abstract class RNode extends RInstall {
|
||||
}
|
||||
throw new RMessage(cmd);
|
||||
}
|
||||
} catch (RMessage rMessage){
|
||||
if (rMessage.getCmd().equals(CommandClass.Command.RETRY)){
|
||||
continue;
|
||||
} else if (rMessage.getCmd().equals(CommandClass.Command.UPLEVEL)){
|
||||
cmd = CommandClass.Command.UPLEVEL;
|
||||
break;
|
||||
} else {
|
||||
throw rMessage;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
if (CommandClass.Command.UPLEVEL.equals(cmd)){
|
||||
this.run(runner);
|
||||
this.runInternal(runner);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -118,7 +131,7 @@ public abstract class RNode extends RInstall {
|
||||
}
|
||||
try {
|
||||
cause = install;
|
||||
install.run(runner);
|
||||
install.runInternal(runner);
|
||||
allRight = true;
|
||||
} catch (InstallException e){
|
||||
exception = e;
|
||||
@@ -137,6 +150,24 @@ public abstract class RNode extends RInstall {
|
||||
}
|
||||
}
|
||||
|
||||
public static RInstall conditional(String keyBoolean, RInstall ifTrue, RInstall ifFalse){
|
||||
return new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Boolean ifBody = (Boolean) runner.requireContext(keyBoolean);
|
||||
if (ifBody){
|
||||
if (ifTrue != null) {
|
||||
ifTrue.run(runner);
|
||||
}
|
||||
} else {
|
||||
if(ifFalse != null) {
|
||||
ifFalse.run(runner);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.xiaomitool.v2.adb.device.DeviceAnswers;
|
||||
import com.xiaomitool.v2.adb.device.DeviceManager;
|
||||
import com.xiaomitool.v2.engine.actions.ActionsDynamic;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.gui.visual.ButtonPane;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.procedure.*;
|
||||
import com.xiaomitool.v2.procedure.install.InstallException;
|
||||
@@ -26,18 +25,8 @@ public class ManageDevice {
|
||||
}
|
||||
|
||||
public static RInstall checkIfTwrpInstalled(){
|
||||
return RNode.sequence(new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
try {
|
||||
device.requireAccessibile();
|
||||
} catch (AdbException e) {
|
||||
throw new InstallException(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
RNode.fallback(RNode.sequence(RebootDevice.rebootRecovery(true, false), TwrpInstall.checkIfIsInTwrp(), new RInstall() {
|
||||
return RNode.sequence(requireAccessible(),
|
||||
RNode.fallback(RNode.sequence(RebootDevice.rebootRecovery(true, false, 15), TwrpInstall.checkIfIsInTwrp(), new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
@@ -46,8 +35,10 @@ public class ManageDevice {
|
||||
}), new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
device.getAnswers().setAnswer(DeviceAnswers.HAS_TWRP, YesNoMaybe.NO);
|
||||
ActionsDynamic.HOWTO_GO_RECOVERY(device).run();
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -62,10 +53,10 @@ public class ManageDevice {
|
||||
}
|
||||
});
|
||||
}
|
||||
public static RInstall checkAccessible(){
|
||||
return checkAccessible(true);
|
||||
public static RInstall requireAccessible(){
|
||||
return requireAccessible(true);
|
||||
}
|
||||
public static RInstall checkNoUnauthOffline(boolean refresh){
|
||||
public static RInstall requireNoUnauthOffline(boolean refresh){
|
||||
return new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
@@ -83,7 +74,7 @@ public class ManageDevice {
|
||||
};
|
||||
}
|
||||
|
||||
public static RInstall checkConnected(boolean refresh){
|
||||
public static RInstall requireConnected(boolean refresh){
|
||||
return new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
@@ -95,23 +86,39 @@ public class ManageDevice {
|
||||
return;
|
||||
}
|
||||
ActionsDynamic.REQUIRE_DEVICE_CONNECTED(device).run();
|
||||
//ActionsDynamic.REQUIRE_DEVICE_AUTH(device).run();
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static RInstall checkAccessible(boolean refresh){
|
||||
return RNode.sequence(checkConnected(refresh), checkNoUnauthOffline(refresh));
|
||||
public static RInstall waitRequireAccessible(int timeout, Device.Status showTextExpectedDeviceStatus){
|
||||
return RNode.sequence(RNode.setSkipOnException(waitDevice(timeout, showTextExpectedDeviceStatus)), requireAccessible(true));
|
||||
}
|
||||
|
||||
public static RInstall requireAccessible(boolean refresh){
|
||||
return RNode.sequence(requireConnected(refresh), requireNoUnauthOffline(refresh));
|
||||
}
|
||||
|
||||
|
||||
public static RInstall waitDevice(int timeout){
|
||||
public static RInstall waitDevice(int timeout, Device.Status showTextExpectedDeviceStatus){
|
||||
return new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
|
||||
if (device.waitActive(timeout) == null){
|
||||
if (showTextExpectedDeviceStatus != null){
|
||||
String connectionType = Device.Status.DEVICE.equals(showTextExpectedDeviceStatus) ? "ADB": showTextExpectedDeviceStatus.toString();
|
||||
runner.text(LRes.WAITING_DEVICE_ACTIVE.toString(connectionType));
|
||||
}
|
||||
int t = timeout;
|
||||
if (t < 2){
|
||||
t = 2;
|
||||
}
|
||||
t-=2;
|
||||
Thread.sleep(1500);
|
||||
device.setConnected(false);
|
||||
DeviceManager.refresh();
|
||||
if (device.waitActive(t) == null){
|
||||
throw new InstallException("Waited device for "+timeout+" seconds but it wasn't active", InstallException.Code.WAIT_DEVICE_TIMEOUT, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.xiaomitool.v2.adb.AdbException;
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.adb.device.DeviceManager;
|
||||
import com.xiaomitool.v2.engine.CommonsMessages;
|
||||
import com.xiaomitool.v2.engine.actions.ActionsStatic;
|
||||
import com.xiaomitool.v2.engine.actions.ActionsDynamic;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.gui.visual.ButtonPane;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
@@ -15,7 +15,7 @@ import com.xiaomitool.v2.procedure.install.InstallException;
|
||||
public class RebootDevice {
|
||||
|
||||
public static RInstall rebootDevice(boolean wait, boolean force){
|
||||
return new RInstall() {
|
||||
return RNode.sequence(ManageDevice.requireAccessible(),new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
@@ -23,6 +23,7 @@ public class RebootDevice {
|
||||
runner.text(LRes.REBOOTING_TO_MODE.toString(Device.Status.DEVICE.toString()));
|
||||
try {
|
||||
if (wait) {
|
||||
runner.text(LRes.WAITING_DEVICE_ACTIVE.toString(Device.Status.DEVICE.toString()));
|
||||
result = device.reboot(Device.Status.DEVICE, force);
|
||||
} else {
|
||||
result = device.rebootNoWait(Device.Status.DEVICE, force);
|
||||
@@ -34,12 +35,14 @@ public class RebootDevice {
|
||||
throw new InstallException("Failed to reboot device to recovery mode", InstallException.Code.REBOOT_FAILED, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static RInstall rebootRecovery(boolean wait, boolean force){
|
||||
return RNode.sequence(rebootDeviceIfNoAdbAccessible(),new RInstall() {
|
||||
return rebootRecovery(wait,force,-1);
|
||||
}
|
||||
public static RInstall rebootRecovery(boolean wait, boolean force, int timeout){
|
||||
return RNode.sequence(ManageDevice.requireAccessible(),rebootDeviceIfNoAdbAccessible(),new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
@@ -47,7 +50,15 @@ public class RebootDevice {
|
||||
runner.text(LRes.REBOOTING_TO_MODE.toString(Device.Status.RECOVERY.toString()));
|
||||
try {
|
||||
if (wait) {
|
||||
result = device.reboot(Device.Status.RECOVERY, force);
|
||||
runner.text(LRes.WAITING_DEVICE_ACTIVE.toString(Device.Status.RECOVERY.toString()));
|
||||
if (timeout <= 0) {
|
||||
result = device.reboot(Device.Status.RECOVERY, force);
|
||||
} else {
|
||||
result = device.rebootNoWait(Device.Status.RECOVERY, force);
|
||||
Thread.sleep(2000);
|
||||
device.setConnected(false);
|
||||
result = result && device.waitStatus(Device.Status.RECOVERY, timeout);
|
||||
}
|
||||
} else {
|
||||
result = device.rebootNoWait(Device.Status.RECOVERY, force);
|
||||
}
|
||||
@@ -62,11 +73,21 @@ public class RebootDevice {
|
||||
}
|
||||
|
||||
public static RInstall rebootNoWaitIfConnected(){
|
||||
return RNode.fallback(rebootDevice(false,false), Procedures.doNothing());
|
||||
return new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
try {
|
||||
device.rebootNoWait(Device.Status.DEVICE,false);
|
||||
} catch (Throwable e) {
|
||||
Log.debug("Device not rebooted, but it doesn't matter");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static RInstall requireRecovery(){
|
||||
return RNode.sequence(ManageDevice.checkAccessible(),new RInstall() {
|
||||
return RNode.sequence(new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
@@ -125,7 +146,7 @@ public class RebootDevice {
|
||||
}
|
||||
|
||||
public static RInstall rebootBootloader(boolean wait, boolean force){
|
||||
return new RInstall() {
|
||||
return RNode.sequence(ManageDevice.requireAccessible(),new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
@@ -133,7 +154,7 @@ public class RebootDevice {
|
||||
runner.text(LRes.REBOOTING_TO_MODE.toString(Device.Status.FASTBOOT.toString()));
|
||||
try {
|
||||
if (wait) {
|
||||
runner.text(LRes.WAITING_DEVICE_ACTIVE);
|
||||
runner.text(LRes.WAITING_DEVICE_ACTIVE.toString(Device.Status.FASTBOOT.toString()));
|
||||
result = device.reboot(Device.Status.FASTBOOT, force);
|
||||
} else {
|
||||
result = device.rebootNoWait(Device.Status.FASTBOOT, force);
|
||||
@@ -145,7 +166,7 @@ public class RebootDevice {
|
||||
throw new InstallException("Failed to reboot device to fastboot mode", InstallException.Code.REBOOT_FAILED, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public static RInstall requireFastboot(){
|
||||
@@ -201,25 +222,14 @@ public class RebootDevice {
|
||||
});
|
||||
}
|
||||
|
||||
public static RInstall rebootStockRecovery(boolean wait, boolean force){
|
||||
return RNode.sequence(rebootDeviceIfNoAdbAccessible(),new RInstall() {
|
||||
public static RInstall rebootStockRecovery(boolean force){
|
||||
return RNode.sequence(ManageDevice.requireAccessible(),rebootDeviceIfNoAdbAccessible(),new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
boolean result = false;
|
||||
runner.text(LRes.REBOOTING_TO_MODE.toString(Device.Status.FASTBOOT.toString()));
|
||||
try {
|
||||
if (wait) {
|
||||
runner.text(LRes.WAITING_DEVICE_ACTIVE);
|
||||
result = device.reboot(Device.Status.FASTBOOT, force);
|
||||
} else {
|
||||
result = device.rebootNoWait(Device.Status.FASTBOOT, force);
|
||||
}
|
||||
} catch (AdbException e){
|
||||
throw new InstallException(e);
|
||||
}
|
||||
boolean result = ActionsDynamic.REBOOT_STOCK_RECOVERY(device,force).run() != 0;
|
||||
if (!result){
|
||||
throw new InstallException("Failed to reboot device to fastboot mode", InstallException.Code.REBOOT_FAILED, false);
|
||||
throw new InstallException("Failed to reboot device to stock recovery mode", InstallException.Code.REBOOT_FAILED, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -240,7 +250,7 @@ public class RebootDevice {
|
||||
}
|
||||
|
||||
public static RInstall requireStockRecovery(){
|
||||
return RNode.sequence(ManageDevice.checkAccessible(),new RInstall() {
|
||||
return RNode.sequence(new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
@@ -252,13 +262,7 @@ public class RebootDevice {
|
||||
while (true) {
|
||||
Log.debug(device.getStatus());
|
||||
try {
|
||||
rebootStockRecovery(false, false).setFlag(RNode.FLAG_THROWRAWEXCEPTION, true).run(runner);
|
||||
ActionsStatic.HOWTO_GO_RECOVERY().run();
|
||||
try {
|
||||
device.waitStatus(Device.Status.SIDELOAD, 120);
|
||||
} catch (AdbException e) {
|
||||
throw new InstallException(e);
|
||||
}
|
||||
rebootStockRecovery(false).setFlag(RNode.FLAG_THROWRAWEXCEPTION, true).run(runner);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.TRY_AGAIN, LRes.ABORT);
|
||||
|
||||
@@ -87,12 +87,12 @@ public class StockRecoveryFetch {
|
||||
}
|
||||
|
||||
public static RInstall allLatestOta(){
|
||||
return RNode.setSkipOnException(RNode.sequence(
|
||||
return RNode.skipOnException(
|
||||
fetchOnlyIfDeviceLockedOrNoFastboot(MiuiRom.Specie.CHINA_STABLE, findInstallWay(MiuiRom.Specie.CHINA_STABLE)),
|
||||
fetchOnlyIfDeviceLockedOrNoFastboot(MiuiRom.Specie.CHINA_DEVELOPER,findInstallWay(MiuiRom.Specie.CHINA_DEVELOPER)),
|
||||
fetchOnlyIfDeviceLockedOrNoFastboot(MiuiRom.Specie.GLOBAL_STABLE,findInstallWay(MiuiRom.Specie.GLOBAL_STABLE)),
|
||||
fetchOnlyIfDeviceLockedOrNoFastboot(MiuiRom.Specie.GLOBAL_DEVELOPER,findInstallWay(MiuiRom.Specie.GLOBAL_DEVELOPER))
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
public static RInstall validatePkgRom(){
|
||||
@@ -120,6 +120,7 @@ public class StockRecoveryFetch {
|
||||
}
|
||||
params.setPkg(md5);
|
||||
HashMap<MiuiRom.Kind, MiuiZipRom> rom ;
|
||||
runner.text(LRes.REQUEST_OTA_INSTALLATION_TOKEN.toString(specie.toString()));
|
||||
try {
|
||||
rom = MiuiRomOta.otaV3_request(params);
|
||||
} catch (XiaomiProcedureException e) {
|
||||
@@ -225,7 +226,7 @@ public class StockRecoveryFetch {
|
||||
params.setPkg(md5);
|
||||
}
|
||||
HashMap<MiuiRom.Kind, MiuiZipRom> rom ;
|
||||
runner.text(LRes.SEARCHING_LATEST_RECOVERY_ROM.toString(params.getSpecie().toString()));
|
||||
runner.text(LRes.SEARCHING_LATEST_OTA_ROM.toString(params.getSpecie().toString()));
|
||||
try {
|
||||
rom = MiuiRomOta.otaV3_request(params);
|
||||
} catch (XiaomiProcedureException e) {
|
||||
@@ -246,14 +247,14 @@ public class StockRecoveryFetch {
|
||||
if (installable == null){
|
||||
throw new InstallException("Ota response doesn't contain an installable rom data", InstallException.Code.MISSING_PROPERTY, true);
|
||||
}
|
||||
if (!installable.hasInstallToken() && !UnlockStatus.UNLOCKED.equals(Procedures.requireDevice(runner).getAnswers().getUnlockStatus()) && installable.getMd5() != null && !installable.getMd5().isEmpty()){
|
||||
/*if (!installable.hasInstallToken() && !UnlockStatus.UNLOCKED.equals(Procedures.requireDevice(runner).getAnswers().getUnlockStatus()) && installable.getMd5() != null && !installable.getMd5().isEmpty()){
|
||||
runner.setContext(SRF_MD5, installable.getMd5());
|
||||
this.run(runner);
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
chooser.add(id, installable);
|
||||
//chooser.add(id, installable);
|
||||
Procedures.setInstallable(runner,installable);
|
||||
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ public class AdbInstall {
|
||||
if (destinationpath == null){
|
||||
destinationpath = "/sdcard/";
|
||||
}
|
||||
String outputPath = destinationpath.endsWith("/") ? (destinationpath+FilenameUtils.getName(fileToPush.toString())) : destinationpath;
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
ProgressPane.DefProgressPane defProgressPane = new ProgressPane.DefProgressPane();
|
||||
UpdateListener listener = defProgressPane.getUpdateListener(200);
|
||||
@@ -56,7 +57,7 @@ public class AdbInstall {
|
||||
defProgressPane.setText(LRes.STARTING_TASK);
|
||||
}
|
||||
});
|
||||
AdbPushTask pushTask = new AdbPushTask(listener,fileToPush, destinationpath, device.getSerial());
|
||||
AdbPushTask pushTask = new AdbPushTask(listener,fileToPush, outputPath, device.getSerial());
|
||||
WindowManager.setMainContent(defProgressPane, false);
|
||||
TaskManager.getInstance().startSameThread(pushTask);
|
||||
pushTask.waitFinished();
|
||||
@@ -64,7 +65,7 @@ public class AdbInstall {
|
||||
if (pushTask.getError() != null){
|
||||
throw new InstallException(new AdbException("Failed to push file on device: "+pushTask.getError().getMessage()));
|
||||
}
|
||||
runner.setContext(OUTPUT_DST_PATH, destinationpath.endsWith("/") ? (destinationpath+FilenameUtils.getName(fileToPush.toString())) : destinationpath);
|
||||
runner.setContext(OUTPUT_DST_PATH, outputPath);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.xiaomitool.v2.procedure.install;
|
||||
|
||||
import com.xiaomitool.v2.adb.AdbException;
|
||||
import com.xiaomitool.v2.adb.AdbUtils;
|
||||
import com.xiaomitool.v2.adb.FastbootCommons;
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
@@ -34,6 +35,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -165,7 +167,12 @@ public class FastbootInstall {
|
||||
String line = (String) arg;
|
||||
Matcher m = p.matcher(line);
|
||||
if (m.find()){
|
||||
procedureRunner.text(m.group(1));
|
||||
String text = m.group(1);
|
||||
procedureRunner.text(text);
|
||||
if (text.toLowerCase().endsWith("system")){
|
||||
procedureRunner.text(LRes.CAN_TAKE_COUPLE_MIN);
|
||||
}
|
||||
|
||||
}
|
||||
lastLine.pointed = line;
|
||||
}
|
||||
@@ -187,6 +194,8 @@ public class FastbootInstall {
|
||||
|
||||
}
|
||||
|
||||
private static final HashMap<String, String> UNLOCK_TOKEN_CACHE = new HashMap<>();
|
||||
|
||||
@ExportFunction("unlock_bootlaoder")
|
||||
public static RInstall unlockBootloader(){
|
||||
return RNode.sequence(RebootDevice.requireFastboot(), new RInstall() {
|
||||
@@ -205,11 +214,13 @@ public class FastbootInstall {
|
||||
throw new InstallException("Failed to get the device unlock token", InstallException.Code.INFO_RETRIVE_FAILED, true);
|
||||
}
|
||||
try {
|
||||
runner.text(LRes.UNLOCK_CHECKING_ACCOUNT);
|
||||
String info = UnlockCommonRequests.userInfo();
|
||||
if (info != null){
|
||||
//TODO
|
||||
Log.debug(info);
|
||||
}
|
||||
runner.text(LRes.UNLOCK_CHECKING_DEVICE);
|
||||
String alert = UnlockCommonRequests.deviceClear((String) device.getDeviceProperties().get(DeviceProperties.CODENAME));
|
||||
if (alert != null){
|
||||
//TODO
|
||||
@@ -228,53 +239,69 @@ public class FastbootInstall {
|
||||
if (click != 0){
|
||||
throw new InstallException("Unlock procedure aborted, cannot continue", InstallException.Code.ABORTED, true);
|
||||
}
|
||||
token = AdbUtils.parseFastbootVar("token",FastbootCommons.getvar("token", device.getSerial()));
|
||||
if (token == null){
|
||||
throw new InstallException("Failed to get the device unlock token", InstallException.Code.INFO_RETRIVE_FAILED, true);
|
||||
}
|
||||
try {
|
||||
String unlockData = null;
|
||||
if (false) { //TODO REMOVE FAKE UNLOCK
|
||||
while (true) {
|
||||
token = AdbUtils.parseFastbootVar("token", FastbootCommons.getvar("token", device.getSerial()));
|
||||
if (token == null) {
|
||||
throw new InstallException("Failed to get the device unlock token", InstallException.Code.INFO_RETRIVE_FAILED, true);
|
||||
}
|
||||
try {
|
||||
String unlockData = null;
|
||||
unlockData = UnlockCommonRequests.ahaUnlock(token, (String) device.getDeviceProperties().get(DeviceProperties.CODENAME), (String) device.getDeviceProperties().getFastbootProperties().get("", ""), (String) device.getDeviceProperties().getFastbootProperties().get("", ""), "");
|
||||
} else {
|
||||
unlockData = "{\"code\":0,\"encryptData\":\"86B700178A7F1BF7886D7A3FA05EBDEECA3095AB4D091C2750A313F1310EF2E898DB92ED3CA7E1FD09E17A92D93BEF63C15653ECB848E672B9C892C4A172F117D671F64A49846A768E95FEAD6643F09D723AC90847D738B8AC12BDB29C8DE2B3AB9A855729A655BDF8A5A0E69B8AC102E78C673D836A808D400157F7FF305BE567AAB5D640FCFBA3229B63F77D81DDABCF2CC01B57E7400D0081547B99F92E2F470CB5B7DF2F43318F0F9205A315FFD19981FC9662371BA4C157A528B448B1BAF5D1D950E349504240DB4BA4AE57C57B85B24834F6130651D555437C24BE0EFFEB7E1277925AFB1D631B66012BBA78CE6161F7C6AF50021BF0849BF15AFD6F42\",\"description\":\"私钥签名成功\",\"uid\":\"1606054557\"}";
|
||||
}
|
||||
if (unlockData == null){
|
||||
throw new InstallException("Failed to get the unlock data required", InstallException.Code.INFO_RETRIVE_FAILED, true);
|
||||
}
|
||||
Log.debug(unlockData);
|
||||
JSONObject json = new JSONObject(unlockData);
|
||||
int code = json.optInt("code",-100);
|
||||
String description = json.optString("description", "null");
|
||||
String encryptData = json.optString("encryptData",null);
|
||||
if (unlockData == null) {
|
||||
throw new InstallException("Failed to get the unlock data required", InstallException.Code.INFO_RETRIVE_FAILED, true);
|
||||
}
|
||||
Log.debug(unlockData);
|
||||
JSONObject json = new JSONObject(unlockData);
|
||||
int code = json.optInt("code", -100);
|
||||
String description = json.optString("description", "null");
|
||||
String encryptData = json.optString("encryptData", null);
|
||||
Log.debug(description);
|
||||
if (code != 0 || encryptData == null) {
|
||||
// throw new InstallException("The server responded, but the unlock is not permitted, code: " + code + ", description: " + description, InstallException.Code.XIAOMI_EXCEPTION, true);
|
||||
ButtonPane unlockButtonPane = new ButtonPane(LRes.TRY_AGAIN, LRes.ABORT);
|
||||
unlockButtonPane.setContentText(LRes.UNLOCK_ERROR_TEXT.toString(code, UnlockCommonRequests.getUnlockCodeMeaning(code,json)));
|
||||
WindowManager.setMainContent(unlockButtonPane,false);
|
||||
int choice = unlockButtonPane.waitClick();
|
||||
WindowManager.removeTopContent();
|
||||
if(choice == 0){
|
||||
continue;
|
||||
} else {
|
||||
throw InstallException.ABORT_EXCEPTION;
|
||||
}
|
||||
} else {
|
||||
UNLOCK_TOKEN_CACHE.put(token, encryptData);
|
||||
}
|
||||
YesNoMaybe unlocked = FastbootCommons.oemUnlock(device.getSerial(), encryptData);
|
||||
if (YesNoMaybe.NO.equals(unlocked)) {
|
||||
throw new InstallException("Failed to unlock the device, fastboot exit with status non zero or internal error", InstallException.Code.UNLOCK_ERROR, true);
|
||||
}
|
||||
device.getDeviceProperties().getFastbootProperties().put(DeviceProperties.X_LOCKSTATUS, UnlockStatus.UNKNOWN);
|
||||
Thread.sleep(1000);
|
||||
DeviceManager.refresh();
|
||||
try {
|
||||
device.waitStatus(Device.Status.FASTBOOT, 4);
|
||||
Device.Status status = device.getStatus();
|
||||
if (Device.Status.FASTBOOT.equals(status)) {
|
||||
device.getDeviceProperties().getFastbootProperties().parse(true);
|
||||
}
|
||||
if (UnlockStatus.LOCKED.equals(device.getAnswers().getUnlockStatus())) {
|
||||
throw new InstallException("Failed to unlock the device, the procedure failed during the unlock command, the device doens't seem to be unlocked", UNLOCK_ERROR, true);
|
||||
}
|
||||
} catch (AdbException e){
|
||||
//Device not in fastboot after 4 seconds = unlock success;
|
||||
Log.debug("Successful unlock!");
|
||||
}
|
||||
break;
|
||||
|
||||
if (code != 0 || encryptData == null){
|
||||
throw new InstallException("The server responded, but the unlock is not permitted, code: "+code+", description: "+description, InstallException.Code.XIAOMI_EXCEPTION, true);
|
||||
} catch (XiaomiProcedureException e) {
|
||||
throw new InstallException(e);
|
||||
} catch (CustomHttpException e) {
|
||||
throw new InstallException(e);
|
||||
} catch (InstallException e) {
|
||||
throw e;
|
||||
} catch (Exception e){
|
||||
throw new InstallException("Internal error while parsing unlock data: "+e.getMessage(), InstallException.Code.INTERNAL_ERROR, true);
|
||||
}
|
||||
YesNoMaybe unlocked = FastbootCommons.oemUnlock(device.getSerial(), encryptData);
|
||||
if (YesNoMaybe.NO.equals(unlocked)){
|
||||
throw new InstallException("Failed to unlock the device, fastboot exit with status non zero or internal error", InstallException.Code.UNLOCK_ERROR, true);
|
||||
}
|
||||
device.getDeviceProperties().getFastbootProperties().put(DeviceProperties.X_LOCKSTATUS, UnlockStatus.UNKNOWN);
|
||||
Thread.sleep(1000);
|
||||
DeviceManager.refresh();
|
||||
device.waitStatus(Device.Status.FASTBOOT, 4);
|
||||
Device.Status status = device.getStatus();
|
||||
if (Device.Status.FASTBOOT.equals(status)){
|
||||
device.getDeviceProperties().getFastbootProperties().parse(true);
|
||||
}
|
||||
if (UnlockStatus.LOCKED.equals(device.getAnswers().getUnlockStatus())){
|
||||
throw new InstallException("Failed to unlock the device, the procedure failed during the unlock command, the device doens't seem to be unlocked", UNLOCK_ERROR, true);
|
||||
}
|
||||
|
||||
} catch (XiaomiProcedureException e) {
|
||||
throw new InstallException(e);
|
||||
} catch (CustomHttpException e) {
|
||||
throw new InstallException(e);
|
||||
} catch (InstallException e){
|
||||
throw e;
|
||||
} catch (Exception e){
|
||||
throw new InstallException("Internal error while parsing unlock data: "+e.getMessage(), InstallException.Code.INTERNAL_ERROR, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.xiaomitool.v2.procedure.install;
|
||||
|
||||
import com.xiaomitool.v2.adb.AdbCommunication;
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.adb.device.DeviceAnswers;
|
||||
import com.xiaomitool.v2.adb.device.DeviceManager;
|
||||
import com.xiaomitool.v2.adb.device.DeviceProperties;
|
||||
import com.xiaomitool.v2.engine.ToolManager;
|
||||
import com.xiaomitool.v2.engine.actions.ActionsDynamic;
|
||||
@@ -16,6 +18,7 @@ import com.xiaomitool.v2.procedure.*;
|
||||
import com.xiaomitool.v2.procedure.device.ManageDevice;
|
||||
import com.xiaomitool.v2.procedure.device.RebootDevice;
|
||||
import com.xiaomitool.v2.procedure.uistuff.ChooseProcedure;
|
||||
import com.xiaomitool.v2.procedure.uistuff.ConfirmationProcedure;
|
||||
import com.xiaomitool.v2.rom.Installable;
|
||||
import com.xiaomitool.v2.rom.chooser.InstallationRequirement;
|
||||
import com.xiaomitool.v2.tasks.UpdateListener;
|
||||
@@ -32,6 +35,7 @@ import javafx.scene.text.TextAlignment;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import static com.xiaomitool.v2.engine.CommonsMessages.NOOP;
|
||||
|
||||
@@ -117,6 +121,7 @@ public class GenericInstall {
|
||||
return RNode.sequence(RebootDevice.rebootNoWaitIfConnected(), new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, InterruptedException {
|
||||
DeviceManager.stopScanThreads();
|
||||
DonationPane donationPane = new DonationPane();
|
||||
WindowManager.setMainContent(donationPane);
|
||||
int msg = NOOP;
|
||||
@@ -173,7 +178,7 @@ public class GenericInstall {
|
||||
ActionsDynamic.WAIT_USB_DEBUG_ENABLE(device).run();
|
||||
}
|
||||
try {
|
||||
ManageDevice.waitDevice(30).setFlag(RNode.FLAG_THROWRAWEXCEPTION, true).run(runner);
|
||||
ManageDevice.waitDevice(30, Device.Status.DEVICE).setFlag(RNode.FLAG_THROWRAWEXCEPTION, true).run(runner);
|
||||
} catch (InstallException e){
|
||||
Log.warn("Starting next requirement satisfaction without device active");
|
||||
}
|
||||
@@ -206,4 +211,32 @@ public class GenericInstall {
|
||||
};
|
||||
}
|
||||
|
||||
public static RInstall main(){
|
||||
return RNode.sequence(RebootDevice.rebootNoWaitIfConnected(),
|
||||
ChooseProcedure.chooseRomCategory(),
|
||||
ChooseProcedure.chooseRom(),
|
||||
RNode.sequence(ConfirmationProcedure.confirmInstallableProcedure(),
|
||||
ConfirmationProcedure.confirmInstallationStart(),
|
||||
RNode.sequence(ManageDevice.waitRequireAccessible(30, Device.Status.DEVICE),
|
||||
GenericInstall.satisfyAllRequirements(),
|
||||
GenericInstall.resourceFetchWait(),
|
||||
GenericInstall.runInstallProcedure(),
|
||||
GenericInstall.installationSuccess())));
|
||||
/*RebootDevice.rebootNoWaitIfConnected().run(runner);
|
||||
Log.debug("PRO0 CHOOSE CAT");
|
||||
ChooseProcedure.chooseRomCategory().run(runner);
|
||||
Log.debug("PRO0 CHOOSE ROM");
|
||||
ChooseProcedure.chooseRom().run(runner);
|
||||
Log.debug("PRO0 FETCH RESOURCE");
|
||||
ConfirmationProcedure.confirmInstallableProcedure().run(runner);
|
||||
ConfirmationProcedure.confirmInstallationStart().run(runner);
|
||||
runner.text(LRes.WAITING_DEVICE_ACTIVE);
|
||||
ManageDevice.waitDevice(60);
|
||||
GenericInstall.satisfyAllRequirements().run(runner);
|
||||
GenericInstall.resourceFetchWait().run(runner);
|
||||
DeviceManager.refresh();
|
||||
GenericInstall.runInstallProcedure().run(runner);
|
||||
GenericInstall.installationSuccess().run(runner);*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ public class StockRecoveryInstall {
|
||||
if (StrUtils.isNullOrEmpty(token)){
|
||||
throw new InstallException("Empty install token", InstallException.Code.SIDELOAD_INSTALL_FAILED, false);
|
||||
}
|
||||
AdbSideloadTask sideloadTask = new AdbSideloadTask(installable.getFinalFile(), token);
|
||||
AdbSideloadTask sideloadTask = new AdbSideloadTask(installable.getFinalFile(), token, device.getSerial());
|
||||
ProgressPane.DefProgressPane defProgressPane = new ProgressPane.DefProgressPane();
|
||||
UpdateListener listener = defProgressPane.getUpdateListener(300);
|
||||
final Pointer textInstalling = new Pointer();
|
||||
@@ -221,13 +221,13 @@ public class StockRecoveryInstall {
|
||||
progressPane.setContentText(LRes.MTP_INSTALLING_FILE.toString() + "\n" + LRes.DONT_REBOOT_DEVICE.toString());
|
||||
WindowManager.setMainContent(progressPane, false);
|
||||
LocalDateTime startTime = LocalDateTime.now();
|
||||
AdbCommunication.closeAccess();
|
||||
AdbCommunication.getAllAccess();
|
||||
try {
|
||||
adbRunner.runWait(3600);
|
||||
} catch (IOException e) {
|
||||
throw new InstallException("Failed to start mtpinstall process: " + e.getMessage(), InstallException.Code.INTERNAL_ERROR, true);
|
||||
}
|
||||
AdbCommunication.openAccess();
|
||||
AdbCommunication.giveAllAccess();
|
||||
WindowManager.removeTopContent();
|
||||
Duration timeElapsed = Duration.between(startTime, LocalDateTime.now());
|
||||
if (adbRunner.getExitValue() != 0) {
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.xiaomitool.v2.utility.YesNoMaybe;
|
||||
import com.xiaomitool.v2.utility.utils.StrUtils;
|
||||
import javafx.application.Platform;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class TwrpInstall {
|
||||
public static RInstall flashTwrp(){
|
||||
//Log.printStackTrace(new Exception());
|
||||
@@ -39,6 +41,8 @@ public class TwrpInstall {
|
||||
throw new InstallException(new AdbException("Fastboot flash recovery failed, output:" + StrUtils.str(flashOutput)));
|
||||
}
|
||||
FastbootCommons.boot(device.getSerial(),installable.getFinalFile());
|
||||
Thread.sleep(1500);
|
||||
device.setConnected(false);
|
||||
}
|
||||
}, GenericInstall.updateDeviceStatus(null,true,null));
|
||||
}
|
||||
@@ -54,6 +58,7 @@ public class TwrpInstall {
|
||||
}
|
||||
});
|
||||
}
|
||||
private static final String ERASE_DATA_KEY = "erase_the_data";
|
||||
|
||||
@ExportFunction("install_zip_viatwrp")
|
||||
public static RInstall installZip(){
|
||||
@@ -61,10 +66,12 @@ public class TwrpInstall {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
String path = "/sdcard/xmt_push";
|
||||
String path = "/sdcard/xmt_push/";
|
||||
runner.text(LRes.CREATING_DEST_DIR);
|
||||
if (!AdbCommons.fileExists(path, device.getSerial())){
|
||||
AdbCommons.command("mkdir "+path, device.getSerial());
|
||||
if (AdbCommons.adb_shellWithOr("mkdir "+path, device.getSerial(), 4) == null){
|
||||
path = "/sdcard/";
|
||||
}
|
||||
}
|
||||
runner.setContext(AdbInstall.DESTINATION_PATH, path);
|
||||
}
|
||||
@@ -72,6 +79,13 @@ public class TwrpInstall {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
Installable installable = Procedures.requireInstallable(runner);
|
||||
File file = installable.getFinalFile();
|
||||
boolean eraseData = true;
|
||||
if (file != null && file.exists()){
|
||||
eraseData = file.length() > 300000000;
|
||||
}
|
||||
runner.setContext(ERASE_DATA_KEY, Boolean.valueOf(eraseData));
|
||||
String outputPath = (String) runner.requireContext(AdbInstall.OUTPUT_DST_PATH);
|
||||
//ProgressPane.DefProgressPane progressPane = new ProgressPane.DefProgressPane();
|
||||
UpdateListener listener = new UpdateListener();
|
||||
@@ -96,7 +110,22 @@ public class TwrpInstall {
|
||||
|
||||
|
||||
}
|
||||
}, wipeDataCacheOnTwrp());
|
||||
}, RNode.conditional(ERASE_DATA_KEY, wipeDataCacheOnTwrp(), wipeCacheOnTwrp()));
|
||||
}
|
||||
|
||||
public static RInstall wipeCacheOnTwrp(){
|
||||
return RNode.sequence(RebootDevice.requireRecovery(), new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
boolean result = false;
|
||||
result |= (AdbCommons.adb_shell("twrp wipe cache",device.getSerial(), 8) != null);
|
||||
// result |= (AdbCommons.adb_shell("twrp wipe data", device.getSerial(), 10) != null);
|
||||
if (!result){
|
||||
throw new InstallException("Failed to wipe cache: twrp command failed", InstallException.Code.WIPE_FAILED, true ) ;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static RInstall wipeDataCacheOnTwrp(){
|
||||
|
||||
@@ -24,7 +24,7 @@ import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import sun.net.ResourceManager;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
@@ -95,6 +95,7 @@ public class ChooseProcedure {
|
||||
runner.setContext(IS_CHOOSEN_PROCEDURE, Boolean.TRUE);
|
||||
} else {
|
||||
Installable choosenIntallable = optionsInstallable.get(i);
|
||||
Log.debug("Choosen installable: "+choosenIntallable.toLogString());
|
||||
Procedures.setInstallable(runner, choosenIntallable);
|
||||
Log.debug("CHOOSEN INSTALLABLE: "+choosenIntallable);
|
||||
runner.setContext(IS_CHOOSEN_PROCEDURE, Boolean.FALSE);
|
||||
@@ -111,7 +112,7 @@ public class ChooseProcedure {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
ChooserPane.Choice[] choices = new ChooserPane.Choice[]{
|
||||
new ChooserPane.Choice(LRes.CHOOSE_XIAOMI_TITLE.toString(), LRes.CHOOSE_XIAOMI_SUB.toString(), ResourcesManager.b64toImage(ResourceImages.IMG_MILOGO)),
|
||||
new ChooserPane.Choice(LRes.CHOOSE_XIAOMI_TITLE.toString(), LRes.CHOOSE_XIAOMI_SUB.toString(), new Image(DrawableManager.getPng("milogo.png").toString())),
|
||||
new ChooserPane.Choice(LRes.CHOOSE_CUSTOM_TITLE.toString(), LRes.CHOOSE_CUSTOM_SUB.toString(), new Image(DrawableManager.getPng("lineage.png").toString())),
|
||||
new ChooserPane.Choice(LRes.CHOOSE_MOD_TITLE.toString(), LRes.CHOOSE_MOD_SUB.toString(), new Image(DrawableManager.getPng("magisk.png").toString())),
|
||||
new ChooserPane.Choice(LRes.CHOOSE_UNLOCK_TITLE.toString(), LRes.CHOOSE_UNLOCK_SUB.toString(), new Image(DrawableManager.getPng("locker.png").toString()))
|
||||
@@ -129,17 +130,19 @@ public class ChooseProcedure {
|
||||
int i = chooserPane.getIdClickReceiver().waitClick();
|
||||
WindowManager.removeTopContent();
|
||||
RInstall toDoNext = null;
|
||||
String noInternetMsg = LRes.NO_INTERNET_BEFORE_FETCH.toString();
|
||||
String keySkip = "key_skip_no_int";
|
||||
switch (i){
|
||||
case 0:
|
||||
toDoNext = GenericFetch.fetchAllOfficial().next();
|
||||
toDoNext = RNode.sequence(ConfirmationProcedure.suggestInternetIfMissing(noInternetMsg, keySkip), RNode.conditional(keySkip, null, GenericFetch.fetchAllOfficial().next()));
|
||||
idGroup = InstallableChooser.IdGroup.officialRom;
|
||||
break;
|
||||
case 1:
|
||||
toDoNext = GenericFetch.fetchAllUnofficial();
|
||||
toDoNext = RNode.sequence(ConfirmationProcedure.suggestInternetIfMissing(noInternetMsg, keySkip),RNode.conditional(keySkip, null,GenericFetch.fetchAllUnofficial()));
|
||||
idGroup = InstallableChooser.IdGroup.unofficialRoms;
|
||||
break;
|
||||
case 2:
|
||||
toDoNext = GenericFetch.fetchAllMods();
|
||||
toDoNext = RNode.sequence(ConfirmationProcedure.suggestInternetIfMissing(noInternetMsg, keySkip),RNode.conditional(keySkip, null,GenericFetch.fetchAllMods()));
|
||||
idGroup = InstallableChooser.IdGroup.modsAndStuff;
|
||||
break;
|
||||
case 3:
|
||||
|
||||
@@ -4,24 +4,31 @@ import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.gui.visual.ButtonPane;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.procedure.*;
|
||||
import com.xiaomitool.v2.procedure.install.InstallException;
|
||||
import com.xiaomitool.v2.rom.Installable;
|
||||
import com.xiaomitool.v2.rom.chooser.InstallationRequirement;
|
||||
import com.xiaomitool.v2.utility.utils.InetUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ConfirmationProcedure {
|
||||
|
||||
public static final String KEY_BOOL_CONFIRM_STEPS = "bool_confirm_steps";
|
||||
|
||||
|
||||
public static RInstall confirmInstallableProcedure(){
|
||||
return RNode.fallback(new RInstall() {
|
||||
return RNode.sequence(new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Procedures.saveProcedure("confirmInstallableProcedure",this).run(runner);
|
||||
Procedures.saveProcedure("confirmInstallableProcedure",confirmInstallableProcedure()).run(runner);
|
||||
Installable installable = Procedures.requireInstallable(runner);
|
||||
Device device = Procedures.requireDevice(runner);
|
||||
List<InstallationRequirement> requirements = InstallationRequirement.getAllInstallableRequirements(installable,device);
|
||||
runner.setContext(KEY_BOOL_CONFIRM_STEPS, Boolean.TRUE);
|
||||
if (requirements.isEmpty()){
|
||||
Log.debug("No requirements for this installation");
|
||||
return;
|
||||
}
|
||||
StringBuilder text = new StringBuilder(LRes.CONFIRM_REQUIREMENTS_TEXT.toString(LRes.CONTINUE.toString(), LRes.CANCEL.toString()));
|
||||
@@ -34,10 +41,51 @@ public class ConfirmationProcedure {
|
||||
int click = buttonPane.waitClick();
|
||||
WindowManager.removeTopContent();
|
||||
if (click != 0){
|
||||
throw new InstallException("You should not see this text", InstallException.Code.INTERNAL_ERROR, false);
|
||||
runner.setContext(KEY_BOOL_CONFIRM_STEPS, Boolean.FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
},RNode.sequence(ChooseProcedure.chooseRom(), Procedures.runSavedProcedure("confirmInstallableProcedure")));
|
||||
},RNode.conditional(KEY_BOOL_CONFIRM_STEPS, null, RNode.sequence(ChooseProcedure.chooseRom(), Procedures.runSavedProcedure("confirmInstallableProcedure"))));
|
||||
}
|
||||
|
||||
public static RInstall suggestInternetIfMissing(String message, String keyWasSkipped){
|
||||
return new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
if(InetUtils.isInternetAvailable()){
|
||||
runner.setContext(keyWasSkipped, Boolean.FALSE);
|
||||
return;
|
||||
}
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.SKIP, LRes.TRY_AGAIN);
|
||||
buttonPane.setContentText(message);
|
||||
WindowManager.setMainContent(buttonPane,false);
|
||||
int click = buttonPane.waitClick();
|
||||
WindowManager.removeTopContent();
|
||||
if (click == 0){
|
||||
runner.setContext(keyWasSkipped, Boolean.TRUE);
|
||||
return;
|
||||
}
|
||||
this.run(runner);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static final String KEY_BOOL_CONFIRM_INSTALL = "bool_confirm_install";
|
||||
public static RInstall confirmInstallationStart(){
|
||||
return RNode.sequence(new RInstall() {
|
||||
@Override
|
||||
public void run(ProcedureRunner runner) throws InstallException, RMessage, InterruptedException {
|
||||
Procedures.saveProcedure("confirmInstallationStart", confirmInstallationStart()).run(runner);
|
||||
runner.setContext(KEY_BOOL_CONFIRM_INSTALL, Boolean.TRUE);
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.CONTINUE, LRes.CANCEL);
|
||||
buttonPane.setContentText(LRes.CONFIRM_INSTALLATION_START.toString(LRes.CONTINUE));
|
||||
WindowManager.setMainContent(buttonPane,false);
|
||||
int click = buttonPane.waitClick();
|
||||
WindowManager.removeTopContent();
|
||||
if (click != 0){
|
||||
runner.setContext(KEY_BOOL_CONFIRM_INSTALL, Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
}, RNode.conditional(KEY_BOOL_CONFIRM_INSTALL, null, RNode.sequence(ChooseProcedure.chooseRom(), confirmInstallableProcedure(), Procedures.runSavedProcedure("confirmInstallationStart"))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.xiaomitool.v2.utility.Choiceable;
|
||||
import com.xiaomitool.v2.utility.CommandClass;
|
||||
import com.xiaomitool.v2.utility.WaitSemaphore;
|
||||
import com.xiaomitool.v2.utility.utils.SettingsUtils;
|
||||
import com.xiaomitool.v2.utility.utils.StrUtils;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.Codebase;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.MiuiVersion;
|
||||
|
||||
@@ -162,6 +163,11 @@ public abstract class Installable extends CommandClass implements Choiceable {
|
||||
return extractInternal(listener);
|
||||
}
|
||||
|
||||
|
||||
public String toLogString() {
|
||||
return this.getClass().getSimpleName()+" - "+StrUtils.str(this.getType())+"[url:"+StrUtils.str(this.downloadUrl)+",dl:"+StrUtils.str(downloadedFile)+",final:"+StrUtils.str(finalFile)+"]";
|
||||
}
|
||||
|
||||
public void fetchResources(UpdateListener downloadListener, UpdateListener extractListener) {
|
||||
if (fetchResourceThread != null && fetchResourceThread.isAlive()){
|
||||
return;
|
||||
|
||||
@@ -154,6 +154,10 @@ public abstract class MiuiRom extends Installable {
|
||||
|
||||
protected Specie specie;
|
||||
|
||||
public Specie getSpecie() {
|
||||
return specie;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDownloadUrl() {
|
||||
if (downloadUrl != null && !downloadUrl.isEmpty()){
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.procedure.RInstall;
|
||||
import com.xiaomitool.v2.procedure.install.FastbootInstall;
|
||||
import com.xiaomitool.v2.tasks.*;
|
||||
import com.xiaomitool.v2.utility.utils.StrUtils;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.Codebase;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.MiuiVersion;
|
||||
|
||||
@@ -64,6 +65,8 @@ public class MiuiTgzRom extends MiuiRom {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected Object extractInternal(UpdateListener listener) throws Exception {
|
||||
Log.debug("Extracting tgz rom: "+filename);
|
||||
|
||||
@@ -34,8 +34,5 @@ public abstract class ZipRom extends Installable {
|
||||
return TwrpInstall.installZip();
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public ChooserPane.Choice getChoice() {
|
||||
return null;//TODO
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import com.xiaomitool.v2.procedure.install.GenericInstall;
|
||||
import com.xiaomitool.v2.procedure.install.StockRecoveryInstall;
|
||||
import com.xiaomitool.v2.procedure.install.TwrpInstall;
|
||||
import com.xiaomitool.v2.rom.Installable;
|
||||
import com.xiaomitool.v2.rom.MiuiRom;
|
||||
import com.xiaomitool.v2.rom.MiuiZipRom;
|
||||
import com.xiaomitool.v2.utility.YesNoMaybe;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.UnlockStatus;
|
||||
|
||||
@@ -46,7 +48,7 @@ public abstract class InstallationRequirement {
|
||||
public static final InstallationRequirement STOCKRECOVERY_REACHABLE = new InstallationRequirement("stock recovery reachable", USB_DEBUG_ENABLED) {
|
||||
@Override
|
||||
public boolean isSatisfied(Device device) {
|
||||
return !device.getDeviceProperties().getSideloadProperties().isFailed();
|
||||
return !YesNoMaybe.YES.equals(device.getAnswers().hasTwrpRecovery()) && device.getDeviceProperties().getSideloadProperties().isParsed();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -182,13 +184,36 @@ public abstract class InstallationRequirement {
|
||||
}
|
||||
|
||||
public static InstallationRequirement[] getInstallableRequirements(Installable installable, Device device){
|
||||
List<InstallationRequirement> requirementList = new ArrayList<>();
|
||||
List<InstallationRequirement> requirementList = new LinkedList<>();
|
||||
switch (installable.getType()){
|
||||
case RECOVERY:
|
||||
if (installable.hasInstallToken() || installable.isOfficial() && UnlockStatus.UNLOCKED.equals(device.getAnswers().getUnlockStatus())){
|
||||
requirementList.add(STOCKRECOVERY_REACHABLE);
|
||||
} else {
|
||||
Log.debug("Trying get install recovery requirements...");
|
||||
Log.debug("Has iToken? "+installable.hasInstallToken());
|
||||
Log.debug("Is official? "+installable.isOfficial());
|
||||
Log.debug("Bootloader status: "+device.getAnswers().getUnlockStatus());
|
||||
Log.debug("Stock recovery reachable? "+STOCKRECOVERY_REACHABLE.isSatisfied(device));
|
||||
boolean hasStockRecovery = (!UnlockStatus.UNLOCKED.equals(device.getAnswers().getUnlockStatus()) || STOCKRECOVERY_REACHABLE.isSatisfied(device));
|
||||
boolean isStockRecoveryInstallable = (installable.hasInstallToken() || installable.isOfficial()) && (installable instanceof MiuiZipRom);
|
||||
boolean isUnsafeCrossRegionInstallation = false;
|
||||
if (isStockRecoveryInstallable){
|
||||
MiuiZipRom zipRom = (MiuiZipRom) installable;
|
||||
MiuiRom.Specie wantToInstallSpecie = zipRom.getSpecie();
|
||||
MiuiRom.Specie currentSpecie = device.getAnswers().getCurrentSpecie();
|
||||
if (currentSpecie.getZone() != wantToInstallSpecie.getZone()){
|
||||
Log.debug("Different rom zone installation, this might be an unsafe cross region installation");
|
||||
String product = (String) device.getDeviceProperties().get(DeviceProperties.CODENAME);
|
||||
isUnsafeCrossRegionInstallation = !DeviceGroups.isSafeToChangeRecoveryLocked(product);
|
||||
}
|
||||
}
|
||||
if (!isStockRecoveryInstallable){
|
||||
requirementList.add(TWRP_INSTALLED);
|
||||
} else {
|
||||
if (isUnsafeCrossRegionInstallation) {
|
||||
requirementList.add(UNLOCKED_BOOTLOADER);
|
||||
}
|
||||
if (!hasStockRecovery) {
|
||||
requirementList.add(STOCKRECOVERY_REACHABLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IMAGE:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.xiaomitool.v2.tasks;
|
||||
|
||||
import com.xiaomitool.v2.adb.AdbCommunication;
|
||||
import com.xiaomitool.v2.adb.AdbException;
|
||||
import com.xiaomitool.v2.procedure.install.InstallException;
|
||||
import com.xiaomitool.v2.process.AdbRunner;
|
||||
@@ -15,15 +16,17 @@ import java.util.regex.Pattern;
|
||||
public class AdbSideloadTask extends Task {
|
||||
private static final Pattern PROGRESS_MATCH = Pattern.compile("\\[\\s*(\\d+)/\\s*(\\d+)\\]");
|
||||
private File fileToSideload;
|
||||
private String token;
|
||||
public AdbSideloadTask(File fileToSideload, String token){
|
||||
private String token, serial;
|
||||
public AdbSideloadTask(File fileToSideload, String token, String serial){
|
||||
this.fileToSideload = fileToSideload;
|
||||
this.token = token;
|
||||
this.serial = serial;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startInternal() {
|
||||
AdbRunner runner = new AdbRunner();
|
||||
runner.setDeviceSerial(serial);
|
||||
runner.addArgument("sideload");
|
||||
if (fileToSideload == null){
|
||||
this.error(new InstallException("null file to sideload", InstallException.Code.INTERNAL_ERROR, false));
|
||||
@@ -55,12 +58,16 @@ public class AdbSideloadTask extends Task {
|
||||
|
||||
}
|
||||
});
|
||||
AdbCommunication.getAllAccess();
|
||||
try {
|
||||
runner.runWait();
|
||||
} catch (IOException e) {
|
||||
this.error(e);
|
||||
return;
|
||||
} finally {
|
||||
AdbCommunication.giveAllAccess();
|
||||
}
|
||||
|
||||
if (runner.getExitValue() != 0){
|
||||
error(new InstallException(new AdbException("adb sideload exited with status: "+runner.getExitValue())));
|
||||
return;
|
||||
|
||||
@@ -1,29 +1,141 @@
|
||||
package com.xiaomitool.v2.test;
|
||||
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.engine.ToolManager;
|
||||
import com.xiaomitool.v2.engine.actions.ActionsDynamic;
|
||||
import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
|
||||
import com.xiaomitool.v2.gui.visual.ChooserPane;
|
||||
import com.xiaomitool.v2.gui.visual.DragAndDropPane;
|
||||
import com.xiaomitool.v2.gui.visual.TextStackPane;
|
||||
import com.xiaomitool.v2.gui.deviceView.Animatable;
|
||||
import com.xiaomitool.v2.gui.deviceView.AnimatableDeviceView;
|
||||
import com.xiaomitool.v2.gui.deviceView.DeviceRecoveryView;
|
||||
import com.xiaomitool.v2.gui.deviceView.DeviceView;
|
||||
import com.xiaomitool.v2.gui.drawable.DrawableManager;
|
||||
import com.xiaomitool.v2.gui.visual.*;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.resources.ResourcesConst;
|
||||
import com.xiaomitool.v2.resources.ResourcesManager;
|
||||
import javafx.animation.*;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.*;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextAlignment;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public class GuiTest extends Application {
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
Pane pane = new StackPane();
|
||||
ToolManager.init(primaryStage);
|
||||
String[] texts = new String[]{"Prova1", "Prova2", "Prova3", "Prova4"};
|
||||
URL[] imgs = new URL[]{DrawableManager.getPng("usbdbg1"),DrawableManager.getPng("usbdbg2"),DrawableManager.getPng("usbdbg3"),DrawableManager.getPng("usbdbg4")};
|
||||
Image[] imgsfx = new Image[imgs.length];
|
||||
for (int i = 0; i<imgs.length; ++i){
|
||||
imgsfx[i] = new Image(imgs[i].toString(),false);
|
||||
}
|
||||
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
/* new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActionsDynamic.HOW_TO_ENABLE_USB_DEBUGGING(null, false).run();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();*/
|
||||
Log.debug("CCASASAS");
|
||||
/*DeviceRecoveryView deviceRecoveryView = new DeviceRecoveryView(DeviceView.DEVICE_18_9, 400);
|
||||
WindowManager.setMainContent(deviceRecoveryView);
|
||||
deviceRecoveryView.selectOption(2);
|
||||
deviceRecoveryView.animateSelectThird(2000);*/
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActionsDynamic.HOWTO_GO_RECOVERY(null).run();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
|
||||
/* DeviceImgInstructionPane imgInstructionPane = new DeviceImgInstructionPane(WindowManager.getContentHeight() + 30, WindowManager.getContentHeight() - 10, texts, imgsfx, null);
|
||||
WindowManager.setMainContent(imgInstructionPane);
|
||||
try {
|
||||
imgInstructionPane.animate();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
});
|
||||
/*SidePane sidePane = new SidePane();
|
||||
ButtonPane buttonPane = new ButtonPane("Prev","Next");
|
||||
AnimatableDeviceView deviceView = new AnimatableDeviceView(DeviceView.DEVICE_18_9, WindowManager.getContentHeight()+30) {
|
||||
@Override
|
||||
public boolean animate(int step) throws InterruptedException {
|
||||
switch (step){
|
||||
case 0:
|
||||
this.buildCircleTransition(666,1330,-1);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
sidePane.setRight(GuiUtils.center(DeviceView.crop(deviceView,WindowManager.getContentHeight()-10, 20)));
|
||||
Text text = new Text(texts[0]);
|
||||
text.setWrappingWidth(400);
|
||||
text.setFont(Font.font(15));
|
||||
text.setTextAlignment(TextAlignment.CENTER);
|
||||
buttonPane.setContent(text);
|
||||
StackPane stackPane = new StackPane(buttonPane);
|
||||
stackPane.setPadding(new Insets(20,0,40,20));
|
||||
sidePane.setLeft(stackPane);
|
||||
deviceView.setContent(imgs[0]);
|
||||
deviceView.setLenOverlay(WindowManager.requireOverlayPane(), 200, 0.5);
|
||||
WindowManager.setMainContent(sidePane);
|
||||
try {
|
||||
deviceView.animate(0);
|
||||
}catch (Exception e){
|
||||
|
||||
}
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int click = buttonPane.waitClick();
|
||||
if (click == 1){
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception e){
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});*/
|
||||
|
||||
|
||||
/*Pane pane = new StackPane();
|
||||
pane.setBackground(WindowManager.DEFAULT_BACKGROUND);
|
||||
pane.setPrefSize(1000,700);
|
||||
|
||||
@@ -142,9 +254,9 @@ public class GuiTest extends Application {
|
||||
}
|
||||
}).start();*/
|
||||
|
||||
Scene scene = new Scene(pane);
|
||||
/* Scene scene = new Scene(pane);
|
||||
primaryStage.setScene(scene);
|
||||
primaryStage.show();
|
||||
primaryStage.show();*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -72,23 +72,26 @@ public class GuiTest2 extends Application{
|
||||
}
|
||||
if (device == null){
|
||||
device = new Device("88eec8b5");
|
||||
DeviceManager.addDevice(device);
|
||||
}
|
||||
runner.init(null,device);
|
||||
device.getDeviceProperties().getAdbProperties().put(DeviceProperties.CODENAME, "whyred");
|
||||
device.getDeviceProperties().getAdbProperties().put(DeviceProperties.FULL_VERSION, "8.9.10");
|
||||
device.getDeviceProperties().getAdbProperties().put(DeviceProperties.X_SERIAL_NUMBER, 0);
|
||||
device.getDeviceProperties().getAdbProperties().put(DeviceProperties.CODEBASE, "8.1");
|
||||
device.getDeviceProperties().getAdbProperties().put(DeviceProperties.CODENAME, "cepheus");
|
||||
device.getDeviceProperties().getAdbProperties().put(DeviceProperties.FULL_VERSION, "9.3.9");
|
||||
device.getDeviceProperties().getAdbProperties().put(DeviceProperties.X_SERIAL_NUMBER, 1);
|
||||
device.getDeviceProperties().getAdbProperties().put(DeviceProperties.CODEBASE, "9.0");
|
||||
//runner.setContext("prop_"+DeviceProperties.CODENAME,"whyred");
|
||||
GenericInstall.main().run(runner);
|
||||
//FastbootFetch.findAllLatestFastboot().run(runner);
|
||||
ChooseProcedure.chooseRomCategory().run(runner);
|
||||
/*ChooseProcedure.chooseRomCategory().run(runner);
|
||||
ChooseProcedure.chooseRom().run(runner);
|
||||
ConfirmationProcedure.confirmInstallableProcedure().run(runner);
|
||||
ConfirmationProcedure.confirmInstallationStart().run(runner);
|
||||
DeviceManager.initScanThreads();
|
||||
GenericInstall.satisfyAllRequirements().run(runner);
|
||||
GenericInstall.resourceFetchWait().run(runner);
|
||||
DeviceManager.refresh();
|
||||
GenericInstall.runInstallProcedure().run(runner);
|
||||
GenericInstall.installationSuccess().run(runner);
|
||||
GenericInstall.installationSuccess().run(runner);*/
|
||||
//FastbootInstall.findBuildRunFlashAll().run(runner);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -31,26 +31,26 @@ public class Main {
|
||||
System.err.println("Usage: MiOtaUpdates.jar passToken userId");
|
||||
System.exit(1);
|
||||
}*/
|
||||
String aargv[] = new String[]{"V1:isBbO7qT2fhtbwL9sYAWOw1F/3NxY9rEGd/Rpl90v+8g3MPwBcGj+LhM7gm2KKdML2d2Z/ubuxQVmZzlyNSjzunw7/coc/ayIf3HCqBZ9Dxg5EURCySg6KexJHox4JTkNOfLrsKEAIue8xdbjH+d5srzS7oSw1feUoLmo89t9WPye0e2w2UG/MJs+YxW+tBTLOhgbnVz0H9nXBcWQayyZwwuNOiB5HPbfjBX2kM6IBxuHA7cdDRWjSDkDMfVwvch", "513820086"};
|
||||
//String aargv[] = new String[]{"V1:isBbO7qT2fhtbwL9sYAWOw1F/3NxY9rEGd/Rpl90v+8g3MPwBcGj+LhM7gm2KKdML2d2Z/ubuxQVmZzlyNSjzunw7/coc/ayIf3HCqBZ9Dxg5EURCySg6KexJHox4JTkNOfLrsKEAIue8xdbjH+d5srzS7oSw1feUoLmo89t9WPye0e2w2UG/MJs+YxW+tBTLOhgbnVz0H9nXBcWQayyZwwuNOiB5HPbfjBX2kM6IBxuHA7cdDRWjSDkDMfVwvch", "513820086"};
|
||||
//String aar
|
||||
//gv[] = new String[]{"V1:sYLMdrtmr68+XYlt3KEGMvIK33el49rcewgc/Aj2eDbhlxtUYYoC403jFphGxbILHMBOxCZ8jb09lYio/ueuyNEA2FG5GGTYdcWWcK09ydkY/wBzMoVhriDnVRguxt7Qj+Xn52Lo2RbErRDknI35gYeIN4gWRpDGwDeL9qTo8ODgyOftZSYklvth66lqzghIiGBiLUu+suwcbaQ/wh+sZostweENZGAfGkRGNF8FsD0VgBHsi+X5xKFoh+FndaZ1", "1606054557"};
|
||||
|
||||
String gv[] = new String[]{"V1:sYLMdrtmr68+XYlt3KEGMvIK33el49rcewgc/Aj2eDbhlxtUYYoC403jFphGxbILHMBOxCZ8jb09lYio/ueuyNEA2FG5GGTYdcWWcK09ydkY/wBzMoVhriDnVRguxt7Qj+Xn52Lo2RbErRDknI35gYeIN4gWRpDGwDeL9qTo8ODgyOftZSYklvth66lqzghIiGBiLUu+suwcbaQ/wh+sZostweENZGAfGkRGNF8FsD0VgBHsi+X5xKFoh+FndaZ1", "1606054557"};
|
||||
gv = new String[]{"V1:UzVU8KYgKUF+aP6f4QkYe4nJRAa4IB4o9a7MjeCocT+PwZw8pVAI1B0a8atv9RktplQq+EFYLvU+swKN2705sjUXC3nGlb2blWkFgUYFtqrWhxPaM2NLUysFwD5fakuzmDKQAREQK5KrtLVt0nSBRrOi1gkqUyOwn42Pe/TsY6R1oEKqMjtB+0gQJvXe67kECSWaGRM6YLO3SrHIZwfxyViNMLihMppHznq9yWQJfE8bAk96Tsk5N6uZMk69BeVs","1606054557"};
|
||||
|
||||
|
||||
XiaomiKeystore keystore = XiaomiKeystore.getInstance();
|
||||
keystore.setCredentials(aargv[1], aargv[0]);
|
||||
keystore.requireServiceKeyAndToken("miuiromota");
|
||||
RequestParams params = new DeviceRequestParams("jason_global","V10.1.2.0.NCHMIFI","7.1",Branch.STABLE,"0xe92ab831",2);
|
||||
params.setPkg("d8f3965aebf2dbfb0291fb21be6cff1b");
|
||||
keystore.setCredentials(gv[1], gv[0]);
|
||||
//*keystore.requireServiceKeyAndToken("miuiromota");
|
||||
RequestParams params = new DeviceRequestParams("jason_global","V10.1.2.0.NCHMIFI","7.1",Branch.STABLE,"0xb7f63ec7",2);
|
||||
/*params.setPkg("d8f3965aebf2dbfb0291fb21be6cff1b");
|
||||
MiuiRomOta.otaV3_request(params);
|
||||
if (true){
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
scarto = 0;
|
||||
//Log.debug(UnlockCommonRequests.test());VQEBIQEQdAsBSujVP9OjWVoBu7zFTwMHY2VwaGV1cwIEQXtF7A==
|
||||
|
||||
//Log.debug(UnlockCommonRequests.ahaUnlock("VQEBMwEgdAsBSujVP9OjWVoBu7zFT3QLAUro1T/To1laAbu8xU8DCWJlcnlsbGl1bQIEQXtF7A==","dipper","","",""));
|
||||
Log.debug(UnlockCommonRequests.ahaUnlock("VQEBIwEQdAsBSujVP9OjWVoBu7zFTwMJYmVyeWxsaXVtAgRBe0Xs","dipper","","","")); //Please unlock 49 hours later
|
||||
Log.debug(UnlockCommonRequests.ahaUnlock("VQEBIQEQRbgeQ5xHgGiytTxvaushBQMHZGF2aW5jaQIENrrqAw==","scorpio","","","")); //Please unlock 49 hours later
|
||||
//Log.debug(UnlockCommonRequests.ahaUnlock("VQEBIAEQdAsBSujVP9OjWVoBu7zFTwMGZGlwcGVyAgRBe0Xs","dipper","","",""));//Please unlock 337 hours later
|
||||
|
||||
if (true){
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.xiaomitool.v2.utility;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class SilentCompleteFuture<T> extends CompletableFuture<T> {
|
||||
public T getSilently(){
|
||||
try {
|
||||
return super.get();
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,8 @@ public class NumberUtils {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static int double2int(double number) {
|
||||
return Double.valueOf(number).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.xiaomitool.v2.xiaomi;
|
||||
|
||||
|
||||
import com.xiaomitool.v2.adb.device.DeviceGroups;
|
||||
import com.xiaomitool.v2.utility.NotNull;
|
||||
|
||||
public class XiaomiUtilities {
|
||||
@@ -29,6 +30,7 @@ public class XiaomiUtilities {
|
||||
}
|
||||
|
||||
public static String deviceToXiaomiEuName(@NotNull String codename) {
|
||||
codename = DeviceGroups.stripCodename(codename);
|
||||
if (codename.equalsIgnoreCase("aries")) {
|
||||
codename = "MI2";
|
||||
} else if (codename.equalsIgnoreCase("aqua")) {
|
||||
@@ -145,6 +147,30 @@ public class XiaomiUtilities {
|
||||
codename = "HM6";
|
||||
} else if (codename.equalsIgnoreCase("sakura")) {
|
||||
codename = "HM6Pro";
|
||||
} else if (codename.equalsIgnoreCase("ursa")) {
|
||||
codename = "MI8Explorer";
|
||||
} else if (codename.equalsIgnoreCase("beryllium")) {
|
||||
codename = "POCOF1";
|
||||
} else if (codename.equalsIgnoreCase("clover")) {
|
||||
codename = "MIPAD4";
|
||||
} else if (codename.equalsIgnoreCase("perseus")) {
|
||||
codename = "MIMix3";
|
||||
} else if (codename.equalsIgnoreCase("platina")) {
|
||||
codename = "MI8LITE";
|
||||
} else if (codename.equalsIgnoreCase("tulip")) {
|
||||
codename = "HMNote6Pro";
|
||||
} else if (codename.equalsIgnoreCase("equuleus")) {
|
||||
codename = "MI8Pro";
|
||||
} else if (codename.equalsIgnoreCase("lavender")) {
|
||||
codename = "HMNote7";
|
||||
} else if (codename.equalsIgnoreCase("cepheus")) {
|
||||
codename = "MI9";
|
||||
} else if (codename.equalsIgnoreCase("grus")) {
|
||||
codename = "MI9SE";
|
||||
} else if (codename.equalsIgnoreCase("onclite")) {
|
||||
codename = "HM7";
|
||||
} else if (codename.equalsIgnoreCase("violet")) {
|
||||
codename = "HMNote7Pro";
|
||||
}
|
||||
return codename;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ public enum Branch {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static boolean isDev(Branch branch) {
|
||||
return !Branch.STABLE.equals(branch);
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.xiaomitool.v2.xiaomi.miuithings;
|
||||
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.adb.device.DeviceGroups;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.rom.MiuiRom;
|
||||
import com.xiaomitool.v2.utility.Nullable;
|
||||
@@ -51,7 +53,7 @@ public class DefaultRequestParams extends RequestParams implements Cloneable {
|
||||
map.put("v","MIUI-"+version.toString());
|
||||
map.put("bv",version.getBigVersion());
|
||||
map.put("c",codebase.toString());
|
||||
map.put("d",device+specie.getSuffix());
|
||||
map.put("d",device+((DeviceGroups.hasEEARegion(device) && isInternational() && !Branch.isDev(branch)) ? "_eea" : "")+specie.getSuffix()); //TODO fix this mess with specie
|
||||
map.put("g",androidHash);
|
||||
if (!isInternational()){
|
||||
map.put("i",imeiHash);
|
||||
|
||||
@@ -8,6 +8,17 @@ import java.util.List;
|
||||
import static com.xiaomitool.v2.xiaomi.miuithings.MiuiVersion.CompareStatus.NEWER;
|
||||
|
||||
public class MiuiVersion extends KeepOriginClass {
|
||||
|
||||
public static MiuiVersion fromObject(Object miuiVersion){
|
||||
if (miuiVersion instanceof String){
|
||||
return new MiuiVersion((String) miuiVersion);
|
||||
} else if (miuiVersion instanceof MiuiVersion){
|
||||
return (MiuiVersion) miuiVersion;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Branch branch;
|
||||
private List<Integer> numbers;
|
||||
private int bigversion;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.xiaomitool.v2.xiaomi.romota;
|
||||
|
||||
import com.xiaomitool.v2.adb.device.DeviceGroups;
|
||||
import com.xiaomitool.v2.crypto.Hash;
|
||||
import com.xiaomitool.v2.inet.CustomHttpException;
|
||||
import com.xiaomitool.v2.inet.EasyHttp;
|
||||
@@ -239,6 +240,10 @@ public class MiuiRomOta {
|
||||
String region = params.isInternational() ? "global" : "cn";
|
||||
String n = params.getCarrier();
|
||||
String lang = params.getLanguage();
|
||||
if (DeviceGroups.hasEEARegion(device) && params.isInternational() && !Branch.isDev(branch)){
|
||||
region = "eea"; //TODO should be in specie
|
||||
device = device.replace("_global","_eea_global");
|
||||
}
|
||||
String url = String.format("http://update.miui.com/updates/miota-fullrom.php?d=%s&b=%s&r=%s&n=%s&l=%s", device, branch.getCode(), region, n, lang);
|
||||
String result;
|
||||
result = EasyHttp.get(url).getBody();
|
||||
@@ -275,7 +280,9 @@ public class MiuiRomOta {
|
||||
Branch b = params.getBranch();
|
||||
b = b == null ? Branch.STABLE : b.getDual();
|
||||
String branch = Branch.STABLE.equals(b) ? "1" : "0";
|
||||
|
||||
if (DeviceGroups.hasEEARegion(device) && params.isInternational() && !Branch.isDev(b)){
|
||||
device = device.replace("_global","_eea_global"); //TODO should be in specie
|
||||
}
|
||||
String url = "https://update.miui.com/updates/v1/latestverinfo.php";
|
||||
EasyResponse response;
|
||||
|
||||
@@ -306,7 +313,12 @@ public class MiuiRomOta {
|
||||
public static MiuiTgzRom latestFastboot2_request(RequestParams params) throws XiaomiProcedureException, CustomHttpException {
|
||||
String device = params.getModDevice();
|
||||
Branch branch = params.getBranch();
|
||||
|
||||
String region = params.isInternational() ? "global" : "cn";
|
||||
if (DeviceGroups.hasEEARegion(device) && params.isInternational() && !Branch.isDev(branch)){
|
||||
region = "eea"; //TODO should be in specie
|
||||
device = device.replace("_global","_eea_global");
|
||||
}
|
||||
String n = params.getCarrier();
|
||||
String url = String.format("https://update.miui.com/updates/v1/fullromdownload.php?d=%s&b=%s&r=%s&n=%s", device, branch.getCode(), region, n), dl;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.xiaomitool.v2.xiaomi.unlock;
|
||||
|
||||
import com.xiaomitool.v2.inet.CustomHttpException;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.utils.StrUtils;
|
||||
import com.xiaomitool.v2.xiaomi.XiaomiKeystore;
|
||||
import com.xiaomitool.v2.xiaomi.XiaomiProcedureException;
|
||||
@@ -10,8 +12,58 @@ import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class UnlockCommonRequests {
|
||||
private static final HashMap<Integer, LRes> UNLOCK_CODE_MEANING = buildUnlockCodeMeaning();
|
||||
public static String getUnlockCodeMeaning(int code, JSONObject object){
|
||||
LRes languageResource = UNLOCK_CODE_MEANING.get(code);
|
||||
if (languageResource == null){
|
||||
return LRes.UNL_UNKNOWN_ERROR.toString(code);
|
||||
}
|
||||
String toReturn;
|
||||
if (code == 20036){
|
||||
int hours = -1;{
|
||||
try {
|
||||
hours = object.getJSONObject("data").getInt("waitHour");
|
||||
} catch (Throwable t){
|
||||
Log.error("Failed to get waitHour for unlock");
|
||||
}
|
||||
if (hours >= 0){
|
||||
int days = hours/24;
|
||||
int leftHours = hours%24;
|
||||
toReturn = languageResource.toString(days, leftHours);
|
||||
} else {
|
||||
toReturn = LRes.UNL_ERR_20036_NOHOURS.toString();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toReturn = languageResource.toString();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
private static HashMap<Integer, LRes> buildUnlockCodeMeaning(){
|
||||
HashMap<Integer, LRes> map = new HashMap<>();
|
||||
map.put(10000, LRes.UNL_ERR_10000);
|
||||
map.put(10001, LRes.UNL_ERR_10001);
|
||||
map.put(10002, LRes.UNL_ERR_10002);
|
||||
map.put(10003, LRes.UNL_ERR_10003);
|
||||
map.put(10004, LRes.UNL_ERR_10004);
|
||||
map.put(10005, LRes.UNL_ERR_10005);
|
||||
map.put(10006, LRes.UNL_ERR_10006);
|
||||
map.put(20030, LRes.UNL_ERR_20030);
|
||||
map.put(20031, LRes.UNL_ERR_20031);
|
||||
map.put(20032, LRes.UNL_ERR_20032);
|
||||
map.put(20033, LRes.UNL_ERR_20033);
|
||||
map.put(20034, LRes.UNL_ERR_20034);
|
||||
map.put(20035, LRes.UNL_ERR_20035);
|
||||
map.put(20036, LRes.UNL_ERR_20036);
|
||||
map.put(20037, LRes.UNL_ERR_20037);
|
||||
map.put(20041, LRes.UNL_ERR_20037);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
private static final String SID = "miui_unlocktool_client";
|
||||
private static final String CLIENT_VERSION = "3.3.525.23";
|
||||
private static final String CLIENT_VERSION = "3.3.827.31";
|
||||
private static final String NONCEV2 = "/api/v2/nonce";
|
||||
private static final String USERINFOV3 = "/api/v3/unlock/userinfo";
|
||||
private static final String DEVICECLEARV3 = "/api/v2/unlock/device/clear";
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: com.xiaomitool.v2.gui.MainWindow
|
||||
|
||||