first commit
@@ -0,0 +1,4 @@
|
||||
out/
|
||||
res/langa/
|
||||
res/tmp/
|
||||
XiaoMiTool\ V2-cache/
|
||||
@@ -0,0 +1,19 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact name="XiaoMiTool:jar">
|
||||
<output-path>$PROJECT_DIR$/out/artifacts/XiaoMiTool_jar</output-path>
|
||||
<root id="root">
|
||||
<element id="archive" name="XiaoMiTool.jar">
|
||||
<element id="module-output" name="XiaoMiTool" />
|
||||
</element>
|
||||
<element id="file-copy" path="$APPLICATION_HOME_DIR$/redist/annotations-java8.jar" />
|
||||
<element id="library" level="project" name="org.json:json:20180130" />
|
||||
<element id="library" level="project" name="commons-io:commons-io:2.6" />
|
||||
<element id="library" level="module" name="openJFX11" module-name="XiaoMiTool" />
|
||||
<element id="library" level="project" name="commons-codec:commons-codec:1.11" />
|
||||
<element id="library" level="project" name="org.apache.commons:commons-lang3:3.7" />
|
||||
<element id="library" level="project" name="org.apache.httpcomponents:httpclient:4.5.5" />
|
||||
<element id="library" level="project" name="commons-logging:commons-logging:1.2" />
|
||||
<element id="library" level="project" name="org.apache.commons:commons-compress:1.17" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
@@ -0,0 +1,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="commons-codec:commons-codec:1.11" type="repository">
|
||||
<properties maven-id="commons-codec:commons-codec:1.11" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.11/commons-codec-1.11.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
@@ -0,0 +1,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="commons-io:commons-io:2.6" type="repository">
|
||||
<properties maven-id="commons-io:commons-io:2.6" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-io/commons-io/2.6/commons-io-2.6.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
@@ -0,0 +1,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="commons-logging:commons-logging:1.2" type="repository">
|
||||
<properties maven-id="commons-logging:commons-logging:1.2" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-logging/commons-logging/1.2/commons-logging-1.2.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
@@ -0,0 +1,13 @@
|
||||
<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,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="org.apache.commons:commons-compress:1.17" type="repository">
|
||||
<properties maven-id="org.apache.commons:commons-compress:1.17" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-compress/1.17/commons-compress-1.17.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
@@ -0,0 +1,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="org.apache.commons:commons-lang3:3.7" type="repository">
|
||||
<properties maven-id="org.apache.commons:commons-lang3:3.7" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
@@ -0,0 +1,13 @@
|
||||
<component name="libraryTable">
|
||||
<library name="org.apache.httpcomponents:httpclient:4.5.5" type="repository">
|
||||
<properties maven-id="org.apache.httpcomponents:httpclient:4.5.5" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/httpcomponents/httpclient/4.5.5/httpclient-4.5.5.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/httpcomponents/httpcore/4.4.9/httpcore-4.4.9.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-logging/commons-logging/1.2/commons-logging-1.2.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.10/commons-codec-1.10.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
@@ -0,0 +1,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="org.json:json:20180130" type="repository">
|
||||
<properties maven-id="org.json:json:20180130" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/json/json/20180130/json-20180130.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
@@ -0,0 +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">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/XiaoMiTool.iml" filepath="$PROJECT_DIR$/XiaoMiTool.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" 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="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" />
|
||||
<orderEntry type="library" name="org.json:json:20180130" level="project" />
|
||||
<orderEntry type="library" name="commons-codec:commons-codec:1.11" level="project" />
|
||||
<orderEntry type="library" name="commons-logging:commons-logging:1.2" level="project" />
|
||||
<orderEntry type="library" name="commons-io:commons-io:2.6" level="project" />
|
||||
<orderEntry type="library" name="org.apache.commons:commons-compress:1.17" level="project" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$APPLICATION_HOME_DIR$/redist/annotations-java8.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,326 @@
|
||||
-injars out\artifacts\XiaoMiTool_jar\XiaoMiTool.jar
|
||||
-outjars out\artifacts\XiaoMiTool.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'
|
||||
|
||||
-dontshrink
|
||||
-dontoptimize
|
||||
-keepattributes javafx.fxml.FXML,*Annotation*,Signature,EnclosingMethod
|
||||
-adaptresourcefilecontents **.fxml,**.properties,META-INF/MANIFEST.MF
|
||||
-dontwarn
|
||||
-ignorewarnings
|
||||
|
||||
|
||||
|
||||
-keep class !com.xiaomitool.v2.xiaomi.** {
|
||||
<fields>;
|
||||
<methods>;
|
||||
}
|
||||
|
||||
-keep class com.xiaomitool.v2.xiaomi.miuithings.** {
|
||||
<fields>;
|
||||
<methods>;
|
||||
}
|
||||
|
||||
-keepclassmembers,allowshrinking class * {
|
||||
@javafx.fxml.FXML
|
||||
<fields>;
|
||||
@javafx.fxml.FXML
|
||||
<methods>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Keep - Applications. Keep all application classes, along with their 'main' methods.
|
||||
-keepclasseswithmembers public class * {
|
||||
public static void main(java.lang.String[]);
|
||||
}
|
||||
|
||||
# Also keep - Enumerations. Keep the special static methods that are required in
|
||||
# enumeration classes.
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
# Also keep - Database drivers. Keep all implementations of java.sql.Driver.
|
||||
-keep class * extends java.sql.Driver
|
||||
|
||||
# Also keep - Swing UI L&F. Keep all extensions of javax.swing.plaf.ComponentUI,
|
||||
# along with the special 'createUI' method.
|
||||
-keep class * extends javax.swing.plaf.ComponentUI {
|
||||
public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent);
|
||||
}
|
||||
|
||||
# Keep - Native method names. Keep all native class/method names.
|
||||
-keepclasseswithmembers,includedescriptorclasses,allowshrinking class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
# 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 {
|
||||
public static double sin(double);
|
||||
public static double cos(double);
|
||||
public static double tan(double);
|
||||
public static double asin(double);
|
||||
public static double acos(double);
|
||||
public static double atan(double);
|
||||
public static double toRadians(double);
|
||||
public static double toDegrees(double);
|
||||
public static double exp(double);
|
||||
public static double log(double);
|
||||
public static double log10(double);
|
||||
public static double sqrt(double);
|
||||
public static double cbrt(double);
|
||||
public static double IEEEremainder(double,double);
|
||||
public static double ceil(double);
|
||||
public static double floor(double);
|
||||
public static double rint(double);
|
||||
public static double atan2(double,double);
|
||||
public static double pow(double,double);
|
||||
public static int round(float);
|
||||
public static long round(double);
|
||||
public static double random();
|
||||
public static int abs(int);
|
||||
public static long abs(long);
|
||||
public static float abs(float);
|
||||
public static double abs(double);
|
||||
public static int max(int,int);
|
||||
public static long max(long,long);
|
||||
public static float max(float,float);
|
||||
public static double max(double,double);
|
||||
public static int min(int,int);
|
||||
public static long min(long,long);
|
||||
public static float min(float,float);
|
||||
public static double min(double,double);
|
||||
public static double ulp(double);
|
||||
public static float ulp(float);
|
||||
public static double signum(double);
|
||||
public static float signum(float);
|
||||
public static double sinh(double);
|
||||
public static double cosh(double);
|
||||
public static double tanh(double);
|
||||
public static double hypot(double,double);
|
||||
public static double expm1(double);
|
||||
public static double log1p(double);
|
||||
}
|
||||
|
||||
# Remove - Number method calls. Remove all invocations of Number
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.* extends java.lang.Number {
|
||||
public static java.lang.String toString(byte);
|
||||
public static java.lang.Byte valueOf(byte);
|
||||
public static byte parseByte(java.lang.String);
|
||||
public static byte parseByte(java.lang.String,int);
|
||||
public static java.lang.Byte valueOf(java.lang.String,int);
|
||||
public static java.lang.Byte valueOf(java.lang.String);
|
||||
public static java.lang.Byte decode(java.lang.String);
|
||||
public int compareTo(java.lang.Byte);
|
||||
public static java.lang.String toString(short);
|
||||
public static short parseShort(java.lang.String);
|
||||
public static short parseShort(java.lang.String,int);
|
||||
public static java.lang.Short valueOf(java.lang.String,int);
|
||||
public static java.lang.Short valueOf(java.lang.String);
|
||||
public static java.lang.Short valueOf(short);
|
||||
public static java.lang.Short decode(java.lang.String);
|
||||
public static short reverseBytes(short);
|
||||
public int compareTo(java.lang.Short);
|
||||
public static java.lang.String toString(int,int);
|
||||
public static java.lang.String toHexString(int);
|
||||
public static java.lang.String toOctalString(int);
|
||||
public static java.lang.String toBinaryString(int);
|
||||
public static java.lang.String toString(int);
|
||||
public static int parseInt(java.lang.String,int);
|
||||
public static int parseInt(java.lang.String);
|
||||
public static java.lang.Integer valueOf(java.lang.String,int);
|
||||
public static java.lang.Integer valueOf(java.lang.String);
|
||||
public static java.lang.Integer valueOf(int);
|
||||
public static java.lang.Integer getInteger(java.lang.String);
|
||||
public static java.lang.Integer getInteger(java.lang.String,int);
|
||||
public static java.lang.Integer getInteger(java.lang.String,java.lang.Integer);
|
||||
public static java.lang.Integer decode(java.lang.String);
|
||||
public static int highestOneBit(int);
|
||||
public static int lowestOneBit(int);
|
||||
public static int numberOfLeadingZeros(int);
|
||||
public static int numberOfTrailingZeros(int);
|
||||
public static int bitCount(int);
|
||||
public static int rotateLeft(int,int);
|
||||
public static int rotateRight(int,int);
|
||||
public static int reverse(int);
|
||||
public static int signum(int);
|
||||
public static int reverseBytes(int);
|
||||
public int compareTo(java.lang.Integer);
|
||||
public static java.lang.String toString(long,int);
|
||||
public static java.lang.String toHexString(long);
|
||||
public static java.lang.String toOctalString(long);
|
||||
public static java.lang.String toBinaryString(long);
|
||||
public static java.lang.String toString(long);
|
||||
public static long parseLong(java.lang.String,int);
|
||||
public static long parseLong(java.lang.String);
|
||||
public static java.lang.Long valueOf(java.lang.String,int);
|
||||
public static java.lang.Long valueOf(java.lang.String);
|
||||
public static java.lang.Long valueOf(long);
|
||||
public static java.lang.Long decode(java.lang.String);
|
||||
public static java.lang.Long getLong(java.lang.String);
|
||||
public static java.lang.Long getLong(java.lang.String,long);
|
||||
public static java.lang.Long getLong(java.lang.String,java.lang.Long);
|
||||
public static long highestOneBit(long);
|
||||
public static long lowestOneBit(long);
|
||||
public static int numberOfLeadingZeros(long);
|
||||
public static int numberOfTrailingZeros(long);
|
||||
public static int bitCount(long);
|
||||
public static long rotateLeft(long,int);
|
||||
public static long rotateRight(long,int);
|
||||
public static long reverse(long);
|
||||
public static int signum(long);
|
||||
public static long reverseBytes(long);
|
||||
public int compareTo(java.lang.Long);
|
||||
public static java.lang.String toString(float);
|
||||
public static java.lang.String toHexString(float);
|
||||
public static java.lang.Float valueOf(java.lang.String);
|
||||
public static java.lang.Float valueOf(float);
|
||||
public static float parseFloat(java.lang.String);
|
||||
public static boolean isNaN(float);
|
||||
public static boolean isInfinite(float);
|
||||
public static int floatToIntBits(float);
|
||||
public static int floatToRawIntBits(float);
|
||||
public static float intBitsToFloat(int);
|
||||
public static int compare(float,float);
|
||||
public boolean isNaN();
|
||||
public boolean isInfinite();
|
||||
public int compareTo(java.lang.Float);
|
||||
public static java.lang.String toString(double);
|
||||
public static java.lang.String toHexString(double);
|
||||
public static java.lang.Double valueOf(java.lang.String);
|
||||
public static java.lang.Double valueOf(double);
|
||||
public static double parseDouble(java.lang.String);
|
||||
public static boolean isNaN(double);
|
||||
public static boolean isInfinite(double);
|
||||
public static long doubleToLongBits(double);
|
||||
public static long doubleToRawLongBits(double);
|
||||
public static double longBitsToDouble(long);
|
||||
public static int compare(double,double);
|
||||
public boolean isNaN();
|
||||
public boolean isInfinite();
|
||||
public int compareTo(java.lang.Double);
|
||||
public byte byteValue();
|
||||
public short shortValue();
|
||||
public int intValue();
|
||||
public long longValue();
|
||||
public float floatValue();
|
||||
public double doubleValue();
|
||||
public int compareTo(java.lang.Object);
|
||||
public boolean equals(java.lang.Object);
|
||||
public int hashCode();
|
||||
public java.lang.String toString();
|
||||
}
|
||||
|
||||
# Remove - String method calls. Remove all invocations of String
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.String {
|
||||
public static java.lang.String copyValueOf(char[]);
|
||||
public static java.lang.String copyValueOf(char[],int,int);
|
||||
public static java.lang.String valueOf(boolean);
|
||||
public static java.lang.String valueOf(char);
|
||||
public static java.lang.String valueOf(char[]);
|
||||
public static java.lang.String valueOf(char[],int,int);
|
||||
public static java.lang.String valueOf(double);
|
||||
public static java.lang.String valueOf(float);
|
||||
public static java.lang.String valueOf(int);
|
||||
public static java.lang.String valueOf(java.lang.Object);
|
||||
public static java.lang.String valueOf(long);
|
||||
public boolean contentEquals(java.lang.StringBuffer);
|
||||
public boolean endsWith(java.lang.String);
|
||||
public boolean equalsIgnoreCase(java.lang.String);
|
||||
public boolean equals(java.lang.Object);
|
||||
public boolean matches(java.lang.String);
|
||||
public boolean regionMatches(boolean,int,java.lang.String,int,int);
|
||||
public boolean regionMatches(int,java.lang.String,int,int);
|
||||
public boolean startsWith(java.lang.String);
|
||||
public boolean startsWith(java.lang.String,int);
|
||||
public byte[] getBytes();
|
||||
public byte[] getBytes(java.lang.String);
|
||||
public char charAt(int);
|
||||
public char[] toCharArray();
|
||||
public int compareToIgnoreCase(java.lang.String);
|
||||
public int compareTo(java.lang.Object);
|
||||
public int compareTo(java.lang.String);
|
||||
public int hashCode();
|
||||
public int indexOf(int);
|
||||
public int indexOf(int,int);
|
||||
public int indexOf(java.lang.String);
|
||||
public int indexOf(java.lang.String,int);
|
||||
public int lastIndexOf(int);
|
||||
public int lastIndexOf(int,int);
|
||||
public int lastIndexOf(java.lang.String);
|
||||
public int lastIndexOf(java.lang.String,int);
|
||||
public int length();
|
||||
public java.lang.CharSequence subSequence(int,int);
|
||||
public java.lang.String concat(java.lang.String);
|
||||
public java.lang.String replaceAll(java.lang.String,java.lang.String);
|
||||
public java.lang.String replace(char,char);
|
||||
public java.lang.String replaceFirst(java.lang.String,java.lang.String);
|
||||
public java.lang.String[] split(java.lang.String);
|
||||
public java.lang.String[] split(java.lang.String,int);
|
||||
public java.lang.String substring(int);
|
||||
public java.lang.String substring(int,int);
|
||||
public java.lang.String toLowerCase();
|
||||
public java.lang.String toLowerCase(java.util.Locale);
|
||||
public java.lang.String toString();
|
||||
public java.lang.String toUpperCase();
|
||||
public java.lang.String toUpperCase(java.util.Locale);
|
||||
public java.lang.String trim();
|
||||
}
|
||||
|
||||
# Remove - StringBuffer method calls. Remove all invocations of StringBuffer
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.StringBuffer {
|
||||
public java.lang.String toString();
|
||||
public char charAt(int);
|
||||
public int capacity();
|
||||
public int codePointAt(int);
|
||||
public int codePointBefore(int);
|
||||
public int indexOf(java.lang.String,int);
|
||||
public int lastIndexOf(java.lang.String);
|
||||
public int lastIndexOf(java.lang.String,int);
|
||||
public int length();
|
||||
public java.lang.String substring(int);
|
||||
public java.lang.String substring(int,int);
|
||||
}
|
||||
|
||||
# Remove - StringBuilder method calls. Remove all invocations of StringBuilder
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.StringBuilder {
|
||||
public java.lang.String toString();
|
||||
public char charAt(int);
|
||||
public int capacity();
|
||||
public int codePointAt(int);
|
||||
public int codePointBefore(int);
|
||||
public int indexOf(java.lang.String,int);
|
||||
public int lastIndexOf(java.lang.String);
|
||||
public int lastIndexOf(java.lang.String,int);
|
||||
public int length();
|
||||
public java.lang.String substring(int);
|
||||
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(...);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
The .dll files here are distributed by Microsoft Corporation as part of the
|
||||
Windows Driver Kit (available at
|
||||
http://www.microsoft.com/whdc/resources/downloads.mspx) and included here as
|
||||
permitted by the Microsoft Software License Terms.
|
||||
@@ -0,0 +1,4 @@
|
||||
The .dll files here are distributed by Microsoft Corporation as part of the
|
||||
Windows Driver Kit (available at
|
||||
http://www.microsoft.com/whdc/resources/downloads.mspx) and included here as
|
||||
permitted by the Microsoft Software License Terms.
|
||||
@@ -0,0 +1,303 @@
|
||||
[Version]
|
||||
Signature = "$Windows NT$"
|
||||
Class = NvBoot
|
||||
ClassGuid={EAD8C4F6-6102-45c7-AA66-36E6D7204600}
|
||||
Provider = %ProviderName%
|
||||
DriverVer=04/01/2010,1.00.01
|
||||
; CatalogFile=MyCatFile.cat FIXME Need own catlog file, which is signed
|
||||
|
||||
;
|
||||
; This section seems to be required for WinUsb driver installation.
|
||||
; If this section is removed the installer will report an error
|
||||
; "Required section not found in INF file".
|
||||
;
|
||||
[ClassInstall32]
|
||||
Addreg = AndroidWinUsbClassReg
|
||||
|
||||
[AndroidWinUsbClassReg]
|
||||
HKR,,,0,%WinUSB_SvcDesc%
|
||||
HKR,,Icon,,-1
|
||||
|
||||
; ========== Manufacturer/Models sections ===========
|
||||
|
||||
[Manufacturer]
|
||||
%ProviderName% = NvidiaUsb_WinUSB,NTx86,NTamd64
|
||||
|
||||
[NvidiaUsb_WinUSB.NTx86]
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7014
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7015
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7115
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7215
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7315
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7415
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7515
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7615
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7715
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7815
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7915
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f15
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7016
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7116
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7216
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7316
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7416
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7516
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7616
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7716
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7816
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7916
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f16
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7020
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7120
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7220
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7320
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7420
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7520
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7620
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7720
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7820
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7920
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f20
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7030
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7130
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7230
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7330
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7430
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7530
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7630
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7730
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7830
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7930
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f30
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7035
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7135
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7235
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7335
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7435
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7535
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7635
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7735
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7835
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7935
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f35
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7040
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7140
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7240
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7340
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7440
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7540
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7640
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7740
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7840
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7940
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f40
|
||||
|
||||
[NvidiaUsb_WinUSB.NTamd64]
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7014
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7015
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7115
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7130
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7215
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7315
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7415
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7515
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7615
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7715
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7815
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7915
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e15
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f15
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7016
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7116
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7216
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7316
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7416
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7516
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7616
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7716
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7816
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7916
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e16
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f16
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7020
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7120
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7220
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7320
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7420
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7520
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7620
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7720
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7820
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7920
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e20
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f20
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7030
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7130
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7230
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7330
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7430
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7530
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7630
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7730
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7830
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7930
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e30
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f30
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7035
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7135
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7235
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7335
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7435
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7535
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7635
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7735
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7835
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7935
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e35
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f35
|
||||
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7040
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7140
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7240
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7340
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7440
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7540
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7640
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7740
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7840
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7940
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7a40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7b40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7c40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7d40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7e40
|
||||
%USB\NvidiaUsb.DeviceDesc% =NvidiaUsb_Install, USB\VID_0955&PID_7f40
|
||||
|
||||
; =================== Installation ===================
|
||||
|
||||
[NvidiaUsb_Install]
|
||||
Include=winusb.inf
|
||||
Needs=WINUSB.NT
|
||||
|
||||
[NvidiaUsb_Install.Services]
|
||||
Include=winusb.inf
|
||||
AddService=WinUSB,0x00000002,WinUSB_ServiceInstall
|
||||
|
||||
[WinUSB_ServiceInstall]
|
||||
DisplayName = %WinUSB_SvcDesc%
|
||||
ServiceType = 1
|
||||
StartType = 3
|
||||
ErrorControl = 1
|
||||
ServiceBinary = %12%\WinUSB.sys
|
||||
|
||||
[NvidiaUsb_Install.Wdf]
|
||||
KmdfService=WINUSB, WinUsb_Install
|
||||
|
||||
[WinUSB_Install]
|
||||
KmdfLibraryVersion=1.7
|
||||
|
||||
[NvidiaUsb_Install.HW]
|
||||
AddReg=Dev_AddReg
|
||||
|
||||
[Dev_AddReg]
|
||||
; FIXME use our own GUID
|
||||
HKR,,DeviceInterfaceGUIDs,0x10000,"{EAD8C4F6-6102-45c7-AA66-36E6D7204600}"
|
||||
|
||||
[NvidiaUsb_Install.CoInstallers]
|
||||
AddReg=CoInstallers_AddReg
|
||||
CopyFiles=CoInstallers_CopyFiles
|
||||
|
||||
[CoInstallers_AddReg]
|
||||
HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01007.dll,WdfCoInstaller","WinUSBCoInstaller.dll"
|
||||
|
||||
[CoInstallers_CopyFiles]
|
||||
WinUSBCoInstaller.dll
|
||||
WdfCoInstaller01007.dll
|
||||
|
||||
[DestinationDirs]
|
||||
CoInstallers_CopyFiles=11
|
||||
|
||||
; ================= Source Media Section =====================
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DISK_NAME%,,,\i386
|
||||
2 = %DISK_NAME%,,,\amd64
|
||||
|
||||
[SourceDisksFiles.x86]
|
||||
WinUSBCoInstaller.dll=1
|
||||
WdfCoInstaller01007.dll=1
|
||||
|
||||
[SourceDisksFiles.amd64]
|
||||
WinUSBCoInstaller.dll=2
|
||||
WdfCoInstaller01007.dll=2
|
||||
|
||||
; =================== Strings ===================
|
||||
|
||||
[Strings]
|
||||
ProviderName="NVIDIA Corporation"
|
||||
USB\NvidiaUsb.DeviceDesc="NVIDIA USB Boot-recovery driver for Mobile devices"
|
||||
USB\NvidiaUsb.DeviceDescFastboot="NVIDIA Android Fastboot Device"
|
||||
USB\NvidiaUsb.DeviceDescAdbComposite="NVIDIA Android Composite Device"
|
||||
USB\NvidiaUsb.DeviceDescAdbDebug="Android Debug Bridge Interface"
|
||||
WinUSB_SvcDesc="NVIDIA Boot Recovery"
|
||||
DISK_NAME="NVIDIA USB Boot Recovery Install Disk"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Manifest-Version: 1.0
|
||||
Class-Path: annotations-java8.jar json-20180130.jar commons-io-2.6.jar
|
||||
src.zip javafx-swt.jar javafx.web.jar javafx.base.jar javafx.fxml.ja
|
||||
r javafx.media.jar javafx.swing.jar javafx.controls.jar javafx.graphi
|
||||
cs.jar commons-codec-1.11.jar commons-lang3-3.7.jar httpclient-4.5.5.
|
||||
jar httpcore-4.4.9.jar commons-logging-1.2.jar commons-codec-1.10.jar
|
||||
commons-logging-1.2.jar commons-compress-1.17.jar
|
||||
Main-Class: com.xiaomitool.v2.gui.MainWindow
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.xiaomitool.v2.adb;
|
||||
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.process.AdbRunner;
|
||||
import com.xiaomitool.v2.process.ProcessRunner;
|
||||
import com.xiaomitool.v2.resources.ResourcesManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class AdbCommons {
|
||||
private static final int DEFAULT_TIMEOUT = 6;
|
||||
private static final String CHECK_RETURN_CODE = "return_code_is_not_zero";
|
||||
private static String command_string(String cmd){
|
||||
return command(cmd, null);
|
||||
}
|
||||
private static String command_string(String cmd, String device) {
|
||||
ProcessRunner runner = adb_command(cmd, device, DEFAULT_TIMEOUT);
|
||||
if (runner == null){
|
||||
return null;
|
||||
}
|
||||
return runner.getOutputString();
|
||||
}
|
||||
private static List<String> command_list(String cmd){
|
||||
return command_list(cmd, null);
|
||||
}
|
||||
private static List<String> command_list(String cmd, String device) {
|
||||
ProcessRunner runner = adb_command(cmd, device, DEFAULT_TIMEOUT);
|
||||
if (runner == null){
|
||||
return null;
|
||||
}
|
||||
return runner.getOutputLines();
|
||||
}
|
||||
|
||||
public static String command(String cmd, String device){
|
||||
return command(cmd,device,DEFAULT_TIMEOUT);
|
||||
}
|
||||
public static String command(String cmd, String device, int timeout){
|
||||
AdbRunner runner = adb_command(cmd,device,timeout);
|
||||
if (runner == null){
|
||||
return null;
|
||||
}
|
||||
return runner.getOutputString();
|
||||
}
|
||||
|
||||
private static AdbRunner adb_command(String cmd, String device, int timeout) {
|
||||
//Log.debug("Input: adb "+cmd);
|
||||
AdbRunner runner = new AdbRunner();
|
||||
if (device != null){
|
||||
runner.setDeviceSerial(device);
|
||||
}
|
||||
|
||||
List<String> list = new ArrayList<String>();
|
||||
Matcher m = Pattern.compile("([^\"]\\S*|\".+?\")\\s*").matcher(cmd);
|
||||
while (m.find()) {
|
||||
list.add(m.group(1));
|
||||
}
|
||||
|
||||
for (String arg : list){
|
||||
runner.addArgument(arg);
|
||||
}
|
||||
try {
|
||||
runner.runWait(timeout);
|
||||
} catch (IOException e) {
|
||||
Log.debug("Cannot execute adb command \"adb "+cmd+"\", reason: "+e.getMessage());
|
||||
return null;
|
||||
}
|
||||
return runner;
|
||||
}
|
||||
|
||||
public static List<String> devices() {
|
||||
return command_list("devices");
|
||||
}
|
||||
public static String start_server() {
|
||||
return command_string("start-server");
|
||||
}
|
||||
public static String kill_server() {
|
||||
return command_string("kill-server");
|
||||
}
|
||||
public static List<String> getProps(String device) {
|
||||
return command_list("shell -x getprop", device);
|
||||
}
|
||||
public static boolean fileExists(String path, String device){
|
||||
String output = adb_shellWithOr("ls "+path,device, DEFAULT_TIMEOUT);
|
||||
return output != null;
|
||||
}
|
||||
public static String adb_shell(String cmd, String device, int timeout){
|
||||
AdbRunner runner = adb_command("shell -x \""+cmd+"\"",device,timeout);
|
||||
if (runner == null || runner.getExitValue() != 0){
|
||||
return null;
|
||||
}
|
||||
return runner.getOutputString();
|
||||
}
|
||||
|
||||
private 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;
|
||||
}
|
||||
public static File simplePull(String device, String pullPath, String destPath) {
|
||||
Path tmpPath = ResourcesManager.getTmpPath();
|
||||
if (!tmpPath.toFile().exists()){
|
||||
try {
|
||||
Files.createDirectories(tmpPath);
|
||||
} catch (IOException e) {
|
||||
Log.warn("Cannot create tmp dir: "+tmpPath.toString()+" : "+e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Path dest = tmpPath.resolve(destPath);
|
||||
AdbRunner runner = adb_command("pull "+pullPath+" \""+dest.toString()+"\"",device,3600);
|
||||
if (runner == null){
|
||||
return null;
|
||||
}
|
||||
if (runner.getExitValue() != 0){
|
||||
return null;
|
||||
}
|
||||
return dest.toFile();
|
||||
}
|
||||
public static String raw(String device, String command){
|
||||
AdbRunner runner = adb_command("raw "+command,device,30);
|
||||
if (runner == null || runner.getExitValue() != 0){
|
||||
return null;
|
||||
}
|
||||
return runner.getOutputString();
|
||||
}
|
||||
public static String cat(String device, String file){
|
||||
return adb_shellWithOr("cat "+file, device, DEFAULT_TIMEOUT);
|
||||
}
|
||||
|
||||
public static String reboot(String device, String status){
|
||||
return command_string("reboot "+status,device);
|
||||
}
|
||||
public static AdbRunner runner(String cmd, String device, int timeout){
|
||||
return adb_command(cmd, device, timeout);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.xiaomitool.v2.adb;
|
||||
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.adb.device.DeviceManager;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.process.AdbRunner;
|
||||
import com.xiaomitool.v2.utility.RunnableWithArg;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AdbCommunication {
|
||||
public static Thread trackDevicesThread, refreshDevicesThread;
|
||||
private static boolean canInterrupt = true, isTrackDeviceActive=false;
|
||||
private static final int REFRESH_TIME_MS = 2500;
|
||||
private static AdbRunner trackDeviceProcess;
|
||||
public static void startServer(){
|
||||
if (!canInterrupt){
|
||||
Log.debug("Cannot interrupt adb connection");
|
||||
}
|
||||
AdbCommons.start_server();
|
||||
|
||||
}
|
||||
public static void killServer(){
|
||||
if (!canInterrupt){
|
||||
Log.debug("Cannot interrupt adb connection");
|
||||
return;
|
||||
}
|
||||
AdbCommons.kill_server();
|
||||
}
|
||||
public static void restartServer(){
|
||||
killServer();
|
||||
startServer();
|
||||
}
|
||||
|
||||
public static boolean canInterrupt() {
|
||||
return canInterrupt;
|
||||
}
|
||||
|
||||
|
||||
public static void registerAutoScanDevices(){
|
||||
if (refreshDevicesThread != null){
|
||||
return;
|
||||
}
|
||||
Runnable trackDevices = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
trackDeviceProcess = new AdbRunner();
|
||||
trackDeviceProcess.addArgument("track-devices");
|
||||
trackDeviceProcess.addSyncCallback(new RunnableWithArg() {
|
||||
@Override
|
||||
public void run(Object arg) {
|
||||
DeviceManager.refresh();
|
||||
}
|
||||
});
|
||||
try {
|
||||
isTrackDeviceActive = true;
|
||||
trackDeviceProcess.runWait(Integer.MAX_VALUE);
|
||||
} catch (IOException e) {
|
||||
Log.warn("Cannot register device scanner thread via track-devices");
|
||||
isTrackDeviceActive = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
trackDevicesThread = new Thread(trackDevices);
|
||||
trackDevicesThread.start();
|
||||
Runnable scanFastbootAdb = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
DeviceManager.refresh();
|
||||
try {
|
||||
Thread.sleep(REFRESH_TIME_MS);
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
refreshDevicesThread = new Thread(scanFastbootAdb);
|
||||
refreshDevicesThread.start();
|
||||
}
|
||||
|
||||
private static void refereshAdbDevices(){
|
||||
List<String> cmdOut = AdbCommons.devices();
|
||||
if (cmdOut == null){
|
||||
return;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Device.Status> entry : AdbUtils.parseDevices(cmdOut).entrySet()){
|
||||
DeviceManager.cacheDeviceStatus(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
private static void refreshFastbootDevices(){
|
||||
List<String> cmdOut = FastbootCommons.devices();
|
||||
if (cmdOut == null){
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<String, Device.Status> entry : AdbUtils.parseDevices(cmdOut).entrySet()){
|
||||
DeviceManager.cacheDeviceStatus(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void refreshDevices(){
|
||||
refereshAdbDevices();
|
||||
refreshFastbootDevices();
|
||||
}
|
||||
|
||||
public static void closeAccess() {
|
||||
canInterrupt = false;
|
||||
unregisterAutoScanDevices();
|
||||
}
|
||||
public static void openAccess(){
|
||||
canInterrupt = true;
|
||||
registerAutoScanDevices();
|
||||
}
|
||||
private static void unregisterAutoScanDevices(){
|
||||
if (trackDeviceProcess != null){
|
||||
trackDeviceProcess.kill();
|
||||
}
|
||||
if (refreshDevicesThread != null && refreshDevicesThread.isAlive()){
|
||||
refreshDevicesThread.interrupt();
|
||||
}
|
||||
refreshDevicesThread = null;
|
||||
if (trackDevicesThread != null && trackDevicesThread.isAlive()){
|
||||
trackDevicesThread.interrupt();
|
||||
}
|
||||
trackDevicesThread = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.xiaomitool.v2.adb;
|
||||
|
||||
import com.xiaomitool.v2.procedure.install.InstallException;
|
||||
|
||||
public class AdbException extends Exception {
|
||||
public AdbException(){
|
||||
super();
|
||||
}
|
||||
public AdbException(String message){
|
||||
super(message);
|
||||
}
|
||||
public InstallException toInstallException(boolean waitCommand){
|
||||
return new InstallException(this.getMessage(), InstallException.Code.ADB_EXCEPTION, waitCommand);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
package com.xiaomitool.v2.adb;
|
||||
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.File;
|
||||
import java.io.StringReader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class AdbUtils {
|
||||
public static Map<String, Device.Status> parseDevices(List<String> output){
|
||||
HashMap<String, Device.Status> result= new HashMap<>();
|
||||
Pattern pattern = Pattern.compile("^(\\w+)\\s+(\\w+)$");
|
||||
for (String line : output){
|
||||
if (line == null){
|
||||
continue;
|
||||
}
|
||||
line = line.trim();
|
||||
Matcher m = pattern.matcher(line);
|
||||
if (m.matches()){
|
||||
result.put(m.group(1), Device.Status.fromString(m.group(2)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static Map<String, Device.Status> parseTrackDevices(String line){
|
||||
Log.debug("Parsing line: "+line);
|
||||
int lenght = line.length();
|
||||
int offset = 0;
|
||||
HashMap<String, Device.Status> result = new HashMap<>();
|
||||
Pattern pattern = Pattern.compile("^(\\w+)\\s+(\\w+)$");
|
||||
while (offset < lenght-3){
|
||||
|
||||
String num = line.substring(offset, offset+4);
|
||||
Log.debug("("+offset+") num: "+num);
|
||||
int n;
|
||||
try {
|
||||
n = Integer.parseInt(num, 16);
|
||||
} catch (Exception e){
|
||||
Log.warn(e.getMessage());
|
||||
break;
|
||||
}
|
||||
offset+=4;
|
||||
if (n == 0){
|
||||
continue;
|
||||
}
|
||||
String data = line.substring(offset, Integer.min(lenght,offset+n));
|
||||
offset+=n;
|
||||
Log.debug(data);
|
||||
Matcher m = pattern.matcher(data);
|
||||
if (m.matches()){
|
||||
result.put(m.group(1), Device.Status.fromString(m.group(2)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static HashMap<String, String> parseGetProp(List<String> propList){
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
Pattern pattern = Pattern.compile("\\[([^\\]]+)\\]\\s*\\:\\s*\\[([^\\]]+)\\]");
|
||||
for (String line: propList){
|
||||
if (line == null){
|
||||
continue;
|
||||
}
|
||||
line = line.trim();
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
if (matcher.matches()){
|
||||
map.put(matcher.group(1), matcher.group(2));
|
||||
Log.debug("Found prop: "+matcher.group(1)+" -> "+matcher.group(2));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static int[] parseWmSize(String text){
|
||||
Pattern pattern = Pattern.compile("(\\d{3,4})x(\\d{3,4})");
|
||||
Matcher m = pattern.matcher(text);
|
||||
if (!m.find()){
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
int x = Integer.parseInt(m.group(1));
|
||||
int y = Integer.parseInt(m.group(2));
|
||||
if (y/x < 4 && y/x > 0){
|
||||
return new int[]{x,y};
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<String, String> parseFastbootVars(List<String> output){
|
||||
Pattern pattern = Pattern.compile("\\s*\\(bootloader\\)\\s+([^\\s]+)\\s*:\\s*(.*)");
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
for (String line : output){
|
||||
if (line == null){
|
||||
continue;
|
||||
}
|
||||
line = line.trim();
|
||||
Matcher m = pattern.matcher(line);
|
||||
if (m.matches()){
|
||||
map.put(m.group(1),m.group(2));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
public static String parseFastbootVar(String var, String output){
|
||||
if (output == null){
|
||||
return null;
|
||||
}
|
||||
Pattern pattern = Pattern.compile("\\s*"+var+"\\s*:\\s*([^\\n]+)");
|
||||
Matcher m = pattern.matcher(output);
|
||||
if (!m.find()){
|
||||
return null;
|
||||
}
|
||||
return m.group(1).trim();
|
||||
}
|
||||
public static String parseFastbootOemInfo(List<String> output){
|
||||
Pattern pattern = Pattern.compile("Device unlocked:\\s*(\\w+)", Pattern.CASE_INSENSITIVE);
|
||||
for (String line : output){
|
||||
Matcher m = pattern.matcher(line);
|
||||
if (m.find()){
|
||||
String bool = m.group(1);
|
||||
Log.debugLine();
|
||||
Log.debug(bool);
|
||||
Log.debugLine();
|
||||
return "true".equals(bool.trim().toLowerCase()) ? "unlocked" : ("false".equals(bool.trim().toLowerCase()) ? "locked" : "unknown");
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
public static String parseFastbootOemLks(List<String> output){
|
||||
Pattern pattern = Pattern.compile("lks\\s*=\\s*(\\d)", Pattern.CASE_INSENSITIVE);
|
||||
for (String line : output){
|
||||
Matcher m = pattern.matcher(line);
|
||||
if (m.find()){
|
||||
String bool = m.group(1);
|
||||
return "0".equals(bool) ? "unlocked" : "locked";
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
public static HashMap<String, String> parseFeaturesFile(Document document) throws Exception {
|
||||
String STRING_ID = "name";
|
||||
Element root = document.getDocumentElement();
|
||||
NodeList feats = root.getChildNodes();
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
for (int i = 0; i<feats.getLength(); ++i){
|
||||
Node n = feats.item(i);
|
||||
if (n == null || n.getNodeType() != Node.ELEMENT_NODE){
|
||||
continue;
|
||||
}
|
||||
Element e = (Element) n;
|
||||
String id = e.getAttribute(STRING_ID);
|
||||
String value = e.getTextContent();
|
||||
map.put(id,value);
|
||||
}
|
||||
return map;
|
||||
|
||||
}
|
||||
|
||||
public static HashMap<String, String> parseFeaturesFile(String features) throws Exception {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document document = builder.parse(new InputSource(new StringReader(features)));
|
||||
return parseFeaturesFile(document);
|
||||
}
|
||||
public static HashMap<String, String> parseFeaturesFile(File features) throws Exception {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document document = builder.parse(features);
|
||||
return parseFeaturesFile(document);
|
||||
}
|
||||
public static int parseSerialNumber(String sn){
|
||||
if (sn.startsWith("0x") || sn.startsWith("0X")){
|
||||
return parseSerialNumber(sn.substring(2));
|
||||
}
|
||||
try {
|
||||
byte[] bytes = Hex.decodeHex(sn.toCharArray());
|
||||
return ByteBuffer.wrap(bytes).getInt();
|
||||
} catch (Exception e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public static int parseFastbootTokenSerialNumber(String token){
|
||||
try {
|
||||
byte[] data = Base64.getDecoder().decode(token);
|
||||
ByteBuffer buffer = ByteBuffer.wrap(data);
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
buffer.position(data.length-4);
|
||||
return buffer.getInt();
|
||||
} catch (Exception e){
|
||||
Log.warn("Failed to parse fastboot token serial number: "+e.getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
package com.xiaomitool.v2.adb;
|
||||
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.process.FastbootRunner;
|
||||
import com.xiaomitool.v2.process.ProcessRunner;
|
||||
import com.xiaomitool.v2.resources.ResourcesManager;
|
||||
import com.xiaomitool.v2.utility.NotNull;
|
||||
import com.xiaomitool.v2.utility.YesNoMaybe;
|
||||
import com.xiaomitool.v2.utility.utils.ProcessUtils;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class FastbootCommons {
|
||||
private static final int DEFAULT_TIMEOUT = 6;
|
||||
public static String command_string(String cmd){
|
||||
return command_string(cmd,null);
|
||||
}
|
||||
public static String command_string(String cmd, String device) {
|
||||
ProcessRunner runner = command_fast(cmd, device, DEFAULT_TIMEOUT);
|
||||
if (runner == null){
|
||||
return "";
|
||||
}
|
||||
return runner.getOutputString();
|
||||
}
|
||||
public static List<String> command_list(String cmd){
|
||||
return command_list(cmd, null);
|
||||
}
|
||||
public static List<String> command_list(String cmd, String device) {
|
||||
ProcessRunner runner = command_fast(cmd, device,DEFAULT_TIMEOUT);
|
||||
if (runner == null){
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return runner.getOutputLines();
|
||||
}
|
||||
public static FastbootRunner command_fast(String cmd, String device, int timeout) {
|
||||
//Log.debug("Input: fastboot "+cmd);
|
||||
FastbootRunner runner = new FastbootRunner();
|
||||
if (device != null){
|
||||
runner.setDeviceSerial(device);
|
||||
}
|
||||
|
||||
List<String> list = new ArrayList<String>();
|
||||
Matcher m = Pattern.compile("([^\"]\\S*|\".+?\")\\s*").matcher(cmd);
|
||||
while (m.find()) {
|
||||
list.add(m.group(1));
|
||||
}
|
||||
|
||||
for (String arg : list){
|
||||
runner.addArgument(arg);
|
||||
}
|
||||
try {
|
||||
runner.runWait(timeout);
|
||||
} catch (IOException e) {
|
||||
Log.error("Cannot execute fastboot command \"fastboot "+cmd+"\", reason: "+e.getMessage());
|
||||
return null;
|
||||
}
|
||||
return runner;
|
||||
}
|
||||
public static List<String> devices() {
|
||||
return command_list("devices");
|
||||
}
|
||||
public static List<String> getvars(String device){
|
||||
FastbootRunner runner = command_fast("getvar all",device,DEFAULT_TIMEOUT);
|
||||
if (runner == null){
|
||||
return null;
|
||||
}
|
||||
if (runner.getExitValue() != 0){
|
||||
return null;
|
||||
}
|
||||
return runner.getOutputLines();
|
||||
}
|
||||
public static String getvar(String var, String device){
|
||||
FastbootRunner runner = command_fast("getvar "+var,device,DEFAULT_TIMEOUT);
|
||||
if (runner == null){
|
||||
return null;
|
||||
}
|
||||
if (runner.getExitValue() != 0){
|
||||
return "";
|
||||
}
|
||||
return runner.getOutputString();
|
||||
}
|
||||
public static List<String> oemDeviceInfo(String device){
|
||||
return command_list("oem device-info",device);
|
||||
}
|
||||
public static List<String> oemLks(String device){
|
||||
return command_list("oem lks", device);
|
||||
}
|
||||
public static String rebootBootloader(String device){
|
||||
return command_string("reboot-bootloader",device);
|
||||
}
|
||||
public static String reboot(String device){
|
||||
return command_string("reboot",device);
|
||||
}
|
||||
public static String oemEdl(String devce){
|
||||
return command_string("oem edl",devce);
|
||||
}
|
||||
|
||||
public static String flash(String device, File finalFile, String partition){
|
||||
String path;
|
||||
try {
|
||||
path = finalFile.getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
path = finalFile.getAbsolutePath();
|
||||
}
|
||||
FastbootRunner runner = command_fast(device, 120, "flash", partition, path);
|
||||
if (runner == null){
|
||||
return null;
|
||||
}
|
||||
String output = runner.getOutputString();
|
||||
if (runner.getExitValue() != 0){
|
||||
Log.debug("Output of flash is failed");
|
||||
if (output != null) {
|
||||
if (output.toLowerCase().contains("anti-rollback")){
|
||||
return "err:anti-rollback";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public static YesNoMaybe oemUnlock(String device, String token){
|
||||
FastbootRunner runner = command_fast(device, 12, "oem", "unlock", token);
|
||||
if(runner.getExitValue() != 0){
|
||||
return YesNoMaybe.NO;
|
||||
} else {
|
||||
String output = runner.getOutputString();
|
||||
if (output.contains("OKAY") && !output.contains("FAIL")){
|
||||
return YesNoMaybe.YES;
|
||||
}
|
||||
return YesNoMaybe.MAYBE;
|
||||
}
|
||||
}
|
||||
|
||||
private static @NotNull FastbootRunner command_fast(String device, int timeout, String... args) {
|
||||
FastbootRunner runner = new FastbootRunner();
|
||||
runner.setDeviceSerial(device);
|
||||
for (String arg : args){
|
||||
runner.addArgument(arg);
|
||||
}
|
||||
try {
|
||||
runner.runWait(timeout);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
return runner;
|
||||
/**/
|
||||
}
|
||||
|
||||
public static String boot(String serial, File finalFile) {
|
||||
String path;
|
||||
try {
|
||||
path = finalFile.getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
path = finalFile.getAbsolutePath();
|
||||
}
|
||||
FastbootRunner runner = command_fast(serial,120,"boot",path);
|
||||
return ProcessUtils.getOutput(runner);
|
||||
}
|
||||
|
||||
public static String flashDummy(String serial) {
|
||||
Path dummyPath = ResourcesManager.getTmpPath().resolve("dummy_image.img");
|
||||
if (!Files.exists(dummyPath)){
|
||||
try (FileOutputStream outputStream = new FileOutputStream(dummyPath.toFile())) {
|
||||
byte[] data = new byte[1024];
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
outputStream.write(data);
|
||||
}
|
||||
} catch (IOException e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return flash(serial,dummyPath.toFile(), "antirbpass");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package com.xiaomitool.v2.adb.device;
|
||||
|
||||
|
||||
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.WaitSemaphore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Device {
|
||||
|
||||
public enum Status {
|
||||
FASTBOOT("fastboot"),
|
||||
DEVICE("device"),
|
||||
UNAUTHORIZED("unauthorized"),
|
||||
OFFLINE("offline"),
|
||||
EDL("edl"),
|
||||
RECOVERY("recovery"),
|
||||
SIDELOAD("sideload"),
|
||||
UNKNOWN("unknown");
|
||||
private String text;
|
||||
Status(String text){
|
||||
this.text = text;
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return this.text;
|
||||
}
|
||||
public static Status fromString(String text){
|
||||
if (text == null){
|
||||
return UNKNOWN;
|
||||
}
|
||||
for (Status s : Status.values()){
|
||||
if (text.equals(s.toString())){
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
private String serial;
|
||||
private Status status;
|
||||
private boolean isConnected = true, firstOffline = true;
|
||||
private final DeviceProperties deviceProperties ;
|
||||
private final WaitSemaphore deviceActiveSem = new WaitSemaphore(), canBeAccessed = new WaitSemaphore(1);
|
||||
private final DeviceAnswers deviceAnswers;
|
||||
|
||||
public Device(String serial){
|
||||
this(serial,Status.UNKNOWN);
|
||||
}
|
||||
public Device(String serial, String state){
|
||||
this(serial, Status.fromString(state));
|
||||
}
|
||||
public Device(String serial, Status state){
|
||||
this.serial = serial;
|
||||
deviceProperties = new DeviceProperties(this);
|
||||
deviceAnswers = new DeviceAnswers(this);
|
||||
setStatus(state);
|
||||
}
|
||||
public void setStatus(Status status) {
|
||||
try {
|
||||
obtainAccess();
|
||||
} catch (InterruptedException e) {
|
||||
Log.debug("This should never happen");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!status.equals(this.status)){
|
||||
Log.debug("Device "+serial+" status: "+status.toString());
|
||||
}
|
||||
this.status = status;
|
||||
if (Status.FASTBOOT.equals(status)){
|
||||
deviceProperties.getFastbootProperties().parse();
|
||||
} else if (Status.SIDELOAD.equals(status)){
|
||||
deviceProperties.getSideloadProperties().parse();
|
||||
} else if (Status.DEVICE.equals(status)){
|
||||
deviceProperties.getAdbProperties().parse();
|
||||
} else if (Status.RECOVERY.equals(status)){
|
||||
deviceProperties.getRecoveryProperties().parse();
|
||||
}
|
||||
releaseAccess();
|
||||
}
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getSerial() {
|
||||
return serial;
|
||||
}
|
||||
public void requireAccess() throws InterruptedException {
|
||||
canBeAccessed.waitOnce();
|
||||
}
|
||||
public void obtainAccess() throws InterruptedException {
|
||||
canBeAccessed.decrease();
|
||||
}
|
||||
public void releaseAccess(){
|
||||
canBeAccessed.increase();
|
||||
}
|
||||
|
||||
public void setConnected(boolean connected) {
|
||||
Log.debug("Set connected for device "+ serial+": "+connected);
|
||||
isConnected = connected;
|
||||
if (connected){
|
||||
deviceActiveSem.setPermits(1);
|
||||
}
|
||||
}
|
||||
public boolean isConnected() {
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
public DeviceProperties getDeviceProperties(){
|
||||
return deviceProperties;
|
||||
}
|
||||
|
||||
public boolean reboot(Status toStatus) throws InterruptedException, AdbException {
|
||||
return reboot(toStatus,false);
|
||||
}
|
||||
public boolean reboot(Status toStatus, boolean force) throws AdbException, InterruptedException {
|
||||
return reboot(toStatus,force,true);
|
||||
}
|
||||
private boolean reboot(Status toStatus, boolean force, boolean wait) throws AdbException, InterruptedException {
|
||||
requireAccessibile();
|
||||
if (!force && toStatus.equals(this.status)) {
|
||||
Log.debug("Device doesn't need reboot: current status ("+this.status+") is the same as wanted status ("+toStatus+")");
|
||||
return true;
|
||||
}
|
||||
return rebootInternal(toStatus,wait);
|
||||
}
|
||||
public boolean rebootNoWait(Status toStatus, boolean force) throws InterruptedException, AdbException {
|
||||
return reboot(toStatus, force, false);
|
||||
}
|
||||
public boolean rebootNoWait(Status toStatus) throws AdbException, InterruptedException {
|
||||
return rebootNoWait(toStatus, false);
|
||||
}
|
||||
private boolean rebootInternal(Status toStatus, boolean wait) throws InterruptedException, AdbException {
|
||||
if (Status.FASTBOOT.equals(this.status)){
|
||||
return fastbootReboot(toStatus, wait);
|
||||
} else {
|
||||
return adbReboot(toStatus, wait);
|
||||
}
|
||||
}
|
||||
private boolean fastbootReboot(Status toStatus, boolean wait) throws AdbException, InterruptedException {
|
||||
if (Status.FASTBOOT.equals(toStatus)){
|
||||
FastbootCommons.rebootBootloader(serial);
|
||||
return rebootWait(toStatus);
|
||||
} 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");
|
||||
}
|
||||
FastbootCommons.reboot(serial);
|
||||
if (!wait){
|
||||
return true;
|
||||
}
|
||||
if (!rebootWait(Status.DEVICE)){
|
||||
if (isConnected && toStatus.equals(this.status)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return reboot(toStatus,false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean rebootWait(Status toStatus) throws AdbException {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
deviceActiveSem.setPermits(0);
|
||||
firstOffline = true;
|
||||
return waitStatus(toStatus);
|
||||
} catch (InterruptedException e) {
|
||||
Log.warn("Thread interrupted (bad): "+e.getMessage());
|
||||
throw new AdbException("The reboot wait thread was interrupted: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean adbReboot(Status toStatus, boolean wait) throws AdbException {
|
||||
String status = toStatus.toString();
|
||||
if (Status.FASTBOOT.equals(toStatus)){
|
||||
status = "bootloader";
|
||||
}
|
||||
AdbCommons.reboot(serial,status);
|
||||
return !wait || rebootWait(toStatus);
|
||||
}
|
||||
public void requireAccessibile() throws AdbException, InterruptedException {
|
||||
requireAccess();
|
||||
if (!isConnected){
|
||||
throw new AdbException("The device cannot be managed right now: not connected");
|
||||
}
|
||||
if(!(Status.FASTBOOT.equals(this.status) || Status.SIDELOAD.equals(this.status) || Status.RECOVERY.equals(this.status) || Status.DEVICE.equals(this.status))){
|
||||
throw new AdbException("The device cannot be managed right now: not accessibile status: "+this.status.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean waitStatus(@NotNull Status status, int timeout) throws InterruptedException, AdbException {
|
||||
if(!deviceActiveSem.waitOnce(timeout)){
|
||||
throw new AdbException("Waiting device active timed out");
|
||||
}
|
||||
if (status.equals(this.status)){
|
||||
return true;
|
||||
}
|
||||
if (status.equals(Status.OFFLINE) && firstOffline){
|
||||
setConnected(false);
|
||||
firstOffline = false;
|
||||
return waitStatus(status,7);
|
||||
}
|
||||
throw new AdbException("Waited for device status "+status.toString()+", got "+(this.status == null ? "null" : this.status.toString()));
|
||||
}
|
||||
|
||||
public boolean waitStatus(@NotNull Status status) throws InterruptedException, AdbException {
|
||||
switch (status){
|
||||
case DEVICE:
|
||||
return waitStatus(status, 80);
|
||||
case FASTBOOT:
|
||||
return waitStatus(status, 10);
|
||||
case SIDELOAD:
|
||||
return waitStatus(status, 40);
|
||||
case RECOVERY:
|
||||
return waitStatus(status, 40);
|
||||
default:
|
||||
return waitStatus(status, 120);
|
||||
}
|
||||
}
|
||||
public boolean isTurnedOn(){
|
||||
return needAuthorization() || Status.DEVICE.equals(this.status);
|
||||
}
|
||||
public boolean needAuthorization(){
|
||||
return Status.OFFLINE.equals(this.status) || Status.UNAUTHORIZED.equals(this.status);
|
||||
}
|
||||
|
||||
public Status waitActive(int timeout){
|
||||
try {
|
||||
this.deviceActiveSem.waitOnce(timeout);
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
return this.getStatus();
|
||||
}
|
||||
|
||||
public DeviceAnswers getAnswers() {
|
||||
return deviceAnswers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.xiaomitool.v2.adb.device;
|
||||
|
||||
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.utility.YesNoMaybe;
|
||||
import com.xiaomitool.v2.utility.utils.StrUtils;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.UnlockStatus;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class DeviceAnswers {
|
||||
public static final String HAS_TWRP = "has_twrp_recovery";
|
||||
|
||||
private Device device;
|
||||
|
||||
DeviceAnswers(Device device){
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
private final HashMap<String, YesNoMaybe> savedAnswers = new HashMap<>();
|
||||
public YesNoMaybe setAnswer(String key, YesNoMaybe answer){
|
||||
this.savedAnswers.put(key, answer);
|
||||
return answer;
|
||||
}
|
||||
|
||||
private YesNoMaybe isInTwrpRecoveryInternal(){
|
||||
if (!Device.Status.RECOVERY.equals(device.getStatus())){
|
||||
return YesNoMaybe.NO;
|
||||
}
|
||||
String random = StrUtils.randomWord(8).toLowerCase();
|
||||
String key_test = "xmt_rand";
|
||||
|
||||
AdbRunner runner = AdbCommons.runner("shell twrp set "+key_test+" "+random,device.getSerial(),6);
|
||||
if (runner.getExitValue() != 0){
|
||||
return YesNoMaybe.MAYBE;
|
||||
}
|
||||
String output = runner.getOutputString();
|
||||
if (output == null){
|
||||
return YesNoMaybe.NO;
|
||||
}
|
||||
if (output.toLowerCase().contains("twrp does not appear to be running")){
|
||||
return YesNoMaybe.MAYBE;
|
||||
}
|
||||
runner = AdbCommons.runner("shell twrp get "+key_test,device.getSerial(),6);
|
||||
if (runner.getExitValue() != 0){
|
||||
return YesNoMaybe.MAYBE;
|
||||
}
|
||||
String output2 = runner.getOutputString();
|
||||
if (output2 == null){
|
||||
return YesNoMaybe.NO;
|
||||
}
|
||||
return output.contains(random) ? YesNoMaybe.YES : YesNoMaybe.NO;
|
||||
}
|
||||
|
||||
public YesNoMaybe hasTwrpRecovery(){
|
||||
return getAnswer(HAS_TWRP);
|
||||
}
|
||||
|
||||
public YesNoMaybe getAnswer(String id){
|
||||
return this.savedAnswers.get(id);
|
||||
}
|
||||
|
||||
public YesNoMaybe isInTwrpRecovery(){
|
||||
return setAnswer(HAS_TWRP,isInTwrpRecovery(3));
|
||||
}
|
||||
private YesNoMaybe isInTwrpRecovery(int trials){
|
||||
YesNoMaybe result = isInTwrpRecoveryInternal();
|
||||
while (YesNoMaybe.MAYBE.equals(result) && trials > 0){
|
||||
--trials;
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
Log.debug(e);
|
||||
}
|
||||
result = isInTwrpRecoveryInternal();
|
||||
}
|
||||
if (YesNoMaybe.YES.equals(result)){
|
||||
setAnswer(HAS_TWRP, YesNoMaybe.YES);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
public UnlockStatus getUnlockStatus() {
|
||||
String product = (String) device.getDeviceProperties().get(DeviceProperties.CODENAME);
|
||||
if (DeviceGroups.hasUnlockedBootloader(product)) {
|
||||
return UnlockStatus.UNLOCKED;
|
||||
}
|
||||
UnlockStatus status = (UnlockStatus) device.getDeviceProperties().getFastbootProperties().get(DeviceProperties.X_LOCKSTATUS);
|
||||
if (status == null) {
|
||||
status = (UnlockStatus) device.getDeviceProperties().getAdbProperties().get(DeviceProperties.X_LOCKSTATUS);
|
||||
}
|
||||
return status == null ? UnlockStatus.UNKNOWN : status;
|
||||
}
|
||||
private static final String IS_MANUAL_MODE = "manualmode";
|
||||
public YesNoMaybe isRebootManualMode(){
|
||||
return getAnswer(IS_MANUAL_MODE);
|
||||
}
|
||||
public void setRebootManualMode(YesNoMaybe answer){
|
||||
setAnswer(IS_MANUAL_MODE, answer);
|
||||
}
|
||||
private static final String NEED_DEVICE_DEBUG = "needdevicedebug";
|
||||
public YesNoMaybe isNeedDeviceDebug(){
|
||||
return getAnswer(NEED_DEVICE_DEBUG);
|
||||
}
|
||||
public void setNeedDeviceDebug(YesNoMaybe answer){
|
||||
setAnswer(NEED_DEVICE_DEBUG, answer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.xiaomitool.v2.adb.device;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
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> getAndroidOneDevices(){
|
||||
HashSet<String> set = new HashSet<>();
|
||||
set.add("tiare");
|
||||
return set;
|
||||
}
|
||||
private static HashSet<String> getEeaRegionDevices(){
|
||||
HashSet<String> set = new HashSet<>();
|
||||
set.add("cepheus");
|
||||
return set;
|
||||
}
|
||||
|
||||
private static HashSet<String> getAlwaysUnlockedSet(){
|
||||
HashSet<String> set = new HashSet<>();
|
||||
set.add("mione_plus");
|
||||
set.add("aries");
|
||||
set.add("taurus");
|
||||
set.add("pisces");
|
||||
set.add("HM2013022");
|
||||
set.add("HM2013023");
|
||||
set.add("cancro");
|
||||
set.add("armani");
|
||||
set.add("lcsh92_wet_tdd");
|
||||
set.add("lcsh92_wet_jb9");
|
||||
set.add("HM2014011");
|
||||
set.add("mocha");
|
||||
set.add("hammerhead");
|
||||
set.add("dior");
|
||||
set.add("HM2014501");
|
||||
set.add("lte26007");
|
||||
set.add("virgo");
|
||||
set.add("wt86047");
|
||||
set.add("wt88047");
|
||||
set.add("gucci");
|
||||
set.add("ferrari");
|
||||
set.add("leo");
|
||||
set.add("hermes");
|
||||
set.add("latte");
|
||||
return set;
|
||||
|
||||
}
|
||||
private static String stripCode(String codename){
|
||||
if (codename == null){
|
||||
return "";
|
||||
}
|
||||
return codename.replace("_global","").replace("_eea","").replace("_alpha","").replace("_ru","");
|
||||
}
|
||||
|
||||
public static boolean hasUnlockedBootloader(String codename){
|
||||
if (codename == null){
|
||||
return false;
|
||||
}
|
||||
return ALWAYS_UNLOCKED_DEVICES.contains(stripCode(codename));
|
||||
}
|
||||
|
||||
public static boolean hasEEARegion(String codename){
|
||||
if (codename == null){
|
||||
return false;
|
||||
}
|
||||
return EEA_REGION_DEVICES.contains(stripCode(codename));
|
||||
}
|
||||
|
||||
public static boolean isAndroidOneDevice(String codename){
|
||||
if (codename == null){
|
||||
return false;
|
||||
}
|
||||
codename = stripCode(codename);
|
||||
return codename.contains("_sprout") || ANDROID_ONE_DEVICES.contains(codename);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.xiaomitool.v2.adb.device;
|
||||
|
||||
import com.xiaomitool.v2.adb.AdbCommunication;
|
||||
import com.xiaomitool.v2.engine.CommonsMessages;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.MessageReceiver;
|
||||
import javafx.application.Platform;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class DeviceManager {
|
||||
|
||||
|
||||
private static Device selectedDevice = null;
|
||||
private static HashMap<String, Device> deviceMap = new HashMap<>();
|
||||
private static HashMap<String, Device.Status> updatingDevices;
|
||||
private static HashSet<MessageReceiver> messageReceivers = new HashSet<>();
|
||||
public static void initScanThreads(){
|
||||
AdbCommunication.registerAutoScanDevices();
|
||||
}
|
||||
public void addDevice(Device device){
|
||||
deviceMap.put(device.getSerial(), device);
|
||||
}
|
||||
public static void setSelectedDevice(Device device){
|
||||
selectedDevice = device;
|
||||
if (device != null){
|
||||
Log.debug("Device selected: "+device.getSerial());
|
||||
Platform.runLater(()->{WindowManager.toast(LRes.SELECTED_DEVICE.toString(device.getSerial()));});
|
||||
|
||||
}
|
||||
}
|
||||
public static void setSelectedDevice(String serial){
|
||||
setSelectedDevice(deviceMap.get(serial));
|
||||
}
|
||||
|
||||
public static Device getSelectedDevice() {
|
||||
return selectedDevice;
|
||||
}
|
||||
|
||||
public static void refresh(){
|
||||
updatingDevices = new HashMap<>();
|
||||
AdbCommunication.refreshDevices();
|
||||
for (Map.Entry<String, Device.Status> entry : updatingDevices.entrySet()){
|
||||
|
||||
Log.debug(entry.getKey() + " - "+entry.getValue());
|
||||
}
|
||||
for (Device d : deviceMap.values()){
|
||||
if (!Device.Status.EDL.equals(d.getStatus()) && updatingDevices.get(d.getSerial()) == null) {
|
||||
d.setConnected(false);
|
||||
Log.debug(d.getSerial() + " is not in updating devices");
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, Device.Status> entry : updatingDevices.entrySet()){
|
||||
setDeviceStatus(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
public static int count(){
|
||||
int i = 0;
|
||||
for (Device d : deviceMap.values()){
|
||||
if (d.isConnected()){
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
|
||||
}
|
||||
public static int count(Device.Status wantedStatus){
|
||||
if (wantedStatus == null){
|
||||
return count();
|
||||
}
|
||||
int i = 0;
|
||||
for (Device d : deviceMap.values()){
|
||||
if (d.isConnected() && wantedStatus.equals(d.getStatus())){
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
public static void setDeviceStatus(String serial, Device.Status status){
|
||||
Log.debug("Device status of "+serial+": "+status.toString());
|
||||
Device device = deviceMap.get(serial);
|
||||
if (device == null){
|
||||
device = new Device(serial, status);
|
||||
deviceMap.put(serial, device);
|
||||
message(CommonsMessages.NEW_DEVICE);
|
||||
|
||||
|
||||
}
|
||||
boolean newStatus = !status.equals(device.getStatus());
|
||||
if (newStatus)
|
||||
message(CommonsMessages.DEVICE_UPDATE_STATUS);
|
||||
device.setStatus(status);
|
||||
device.setConnected(true);
|
||||
if(newStatus)
|
||||
message(CommonsMessages.DEVICE_UPDATE_FINISH);
|
||||
|
||||
}
|
||||
public static void cacheDeviceStatus(String serial, Device.Status status){
|
||||
updatingDevices.put(serial,status);
|
||||
}
|
||||
|
||||
public static Device getFirstDevice(){
|
||||
if (deviceMap.size() == 0){
|
||||
return null;
|
||||
}
|
||||
return deviceMap.entrySet().iterator().next().getValue();
|
||||
}
|
||||
|
||||
|
||||
private static void message(int message){
|
||||
for (MessageReceiver messageReceiver : messageReceivers){
|
||||
messageReceiver.message(message);
|
||||
}
|
||||
}
|
||||
public static Collection<Device> getDevices(){
|
||||
return deviceMap.values();
|
||||
}
|
||||
public static void addMessageReceiver(MessageReceiver receiver){
|
||||
messageReceivers.add(receiver);
|
||||
}
|
||||
public static void removeMessageReceiver(MessageReceiver receiver){
|
||||
messageReceivers.remove(receiver);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
package com.xiaomitool.v2.adb.device;
|
||||
|
||||
import com.xiaomitool.v2.adb.AdbCommons;
|
||||
import com.xiaomitool.v2.adb.AdbUtils;
|
||||
import com.xiaomitool.v2.adb.FastbootCommons;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.YesNoMaybe;
|
||||
import com.xiaomitool.v2.utility.utils.ThreadUtils;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.Branch;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.UnlockStatus;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class DeviceProperties {
|
||||
public static final String X_SCREEN_WIDTH = "xmt.screen_x";
|
||||
public static final String X_SCREEN_HEIGHT = "xmt.screen_y";
|
||||
public static final String X_HAS_SU = "xmt.has_su";
|
||||
public static final String X_LOCKSTATUS = "xmt.lockstatus";
|
||||
public static final String CODENAME = "ro.product.device";
|
||||
public static final String FULL_VERSION = "ro.build.version.incremental";
|
||||
public static final String X_SERIAL_NUMBER = "xmt.serial_number";
|
||||
public static final String X_BRANCH = "xmt.branch";
|
||||
public static final String LANGUAGE = "ro.product.locale.language";
|
||||
public static final String REGION = "ro.miui.region";
|
||||
public static final String ROMZONE = "ro.rom.zone";
|
||||
public static final String CODEBASE = "ro.build.version.release";
|
||||
public static final String BRAND = "ro.product.brand";
|
||||
public static final String MODEL = "ro.product.model";
|
||||
|
||||
|
||||
|
||||
class AdbProperties extends Properties {
|
||||
@Override
|
||||
protected boolean parseInternal() {
|
||||
findProps();
|
||||
findScreenDimension();
|
||||
findSu();
|
||||
findUnlockStatusDevice();
|
||||
findSerialNum();
|
||||
String product = this.get(CODENAME,"").toString();
|
||||
if (product.isEmpty()){
|
||||
return false;
|
||||
}
|
||||
findFeatures(product,false);
|
||||
Log.debug("Adb properties parsed");
|
||||
|
||||
return true;
|
||||
}
|
||||
private void findProps(){
|
||||
List<String> propList = AdbCommons.getProps(serial);
|
||||
if (propList == null){
|
||||
Log.warn("Failed to get adb device properties via getprop");
|
||||
return;
|
||||
}
|
||||
this.putAll(AdbUtils.parseGetProp(propList));
|
||||
}
|
||||
private void findScreenDimension(){
|
||||
String res = AdbCommons.command("shell wm size",serial);
|
||||
if (res == null){
|
||||
Log.warn("Failed to get screen dimensions");
|
||||
return;
|
||||
}
|
||||
int[] screenDims = AdbUtils.parseWmSize(res);
|
||||
if (screenDims != null){
|
||||
this.put(X_SCREEN_WIDTH, screenDims[0]);
|
||||
this.put(X_SCREEN_HEIGHT,screenDims[1]);
|
||||
}
|
||||
}
|
||||
private void findSu(){
|
||||
boolean hasSU = false;
|
||||
if (AdbCommons.fileExists("/system/xbin/su", serial)){
|
||||
hasSU = true;
|
||||
} else {
|
||||
hasSU = AdbCommons.fileExists("/system/bin/su", serial);
|
||||
}
|
||||
this.put(X_HAS_SU,hasSU);
|
||||
}
|
||||
private void findUnlockStatusDevice(){
|
||||
|
||||
this.put(X_LOCKSTATUS,DeviceGroups.hasUnlockedBootloader(this.get(CODENAME,"").toString()) ? UnlockStatus.UNLOCKED : UnlockStatus.fromString((String) this.get("ro.secureboot.lockstate")));
|
||||
}
|
||||
private boolean findFeatures(String product, boolean usePull){
|
||||
if (product.contains(" ")) {
|
||||
return false;
|
||||
}
|
||||
String file = "/system/etc/device_features/" + product + ".xml";
|
||||
if (usePull) {
|
||||
|
||||
File features = AdbCommons.simplePull(serial, file, "features.xml");
|
||||
if (features == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
HashMap<String, String> props = AdbUtils.parseFeaturesFile(features);
|
||||
if (props.size() == 0) {
|
||||
throw new Exception("returned hashmap is empty");
|
||||
}
|
||||
this.putAll(props);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.warn("Cannot parse features file: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
String features = AdbCommons.cat(serial, file);
|
||||
if (features == null) {
|
||||
return findFeatures(product, true);
|
||||
}
|
||||
try {
|
||||
HashMap<String, String> props = AdbUtils.parseFeaturesFile(features);
|
||||
if (props.size() == 0) {
|
||||
throw new Exception("Returned hashmap is empty");
|
||||
}
|
||||
this.putAll(props);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.warn("Cannot parse features file: " + e.getMessage());
|
||||
return findFeatures(product, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
private boolean findSerialNum(){
|
||||
String sn = AdbCommons.cat(serial, "/proc/serial_num");
|
||||
if (sn == null){
|
||||
sn = (String) this.get("ro.boot.cpuid",null);
|
||||
if (sn == null){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
int x = AdbUtils.parseSerialNumber(sn);
|
||||
if (x != 0){
|
||||
this.put(X_SERIAL_NUMBER, x);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
class FastbootProperties extends Properties {
|
||||
|
||||
@Override
|
||||
protected boolean parseInternal() {
|
||||
boolean result;
|
||||
result = findUnlockState();
|
||||
findVars();
|
||||
findSerialNumber();
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean findVars(){
|
||||
boolean result = false;
|
||||
HashMap<String, String> getvar = new HashMap<>();
|
||||
List<String> allVars = FastbootCommons.getvars(serial);
|
||||
if (allVars != null){
|
||||
getvar = AdbUtils.parseFastbootVars(allVars);
|
||||
if (getvar.size() > 0){
|
||||
this.putAll(getvar);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
String[] toGetVars = new String[]{"product","unlocked","token"};
|
||||
for (String var : toGetVars){
|
||||
String out = FastbootCommons.getvar(var, serial);
|
||||
if (out == null){
|
||||
continue;
|
||||
}
|
||||
if (out.isEmpty()){
|
||||
continue;
|
||||
}
|
||||
String value = AdbUtils.parseFastbootVar(var, out);
|
||||
if (value != null){
|
||||
this.put(var, value);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean findSerialNumber(){
|
||||
String token = get("token","").toString();
|
||||
if (token.isEmpty()){
|
||||
return false;
|
||||
}
|
||||
Integer x = AdbUtils.parseFastbootTokenSerialNumber(token);
|
||||
if (x != 0){
|
||||
this.put(X_SERIAL_NUMBER, x);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean findUnlockState(){
|
||||
try {
|
||||
if (DeviceGroups.hasUnlockedBootloader(device.getDeviceProperties().getAdbProperties().get(CODENAME,"").toString()) || DeviceGroups.hasUnlockedBootloader(device.getDeviceProperties().getSideloadProperties().get(CODENAME,"").toString())){
|
||||
this.put(X_LOCKSTATUS, UnlockStatus.UNLOCKED);
|
||||
return true;
|
||||
}
|
||||
} catch (Throwable t){
|
||||
Log.debug(t.getMessage());
|
||||
}
|
||||
List<String> output = FastbootCommons.oemDeviceInfo(serial);
|
||||
if (output == null){
|
||||
return false;
|
||||
}
|
||||
UnlockStatus status = UnlockStatus.fromString(AdbUtils.parseFastbootOemInfo(output));
|
||||
if (status != UnlockStatus.UNKNOWN){
|
||||
this.put(X_LOCKSTATUS, status);
|
||||
return true;
|
||||
}
|
||||
output = FastbootCommons.oemLks(serial);
|
||||
if (output == null){
|
||||
return false;
|
||||
}
|
||||
status = UnlockStatus.fromString(AdbUtils.parseFastbootOemLks(output));
|
||||
if (status != UnlockStatus.UNKNOWN){
|
||||
this.put(X_LOCKSTATUS, status);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class SideloadProperties extends Properties {
|
||||
|
||||
@Override
|
||||
protected boolean parseInternal() {
|
||||
findProps();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean findProps() {
|
||||
String value;
|
||||
value = AdbCommons.raw(serial, "getdevice:");
|
||||
if (value != null) {
|
||||
this.put(CODENAME, value.replace("_global",""));
|
||||
}
|
||||
ThreadUtils.sleepSilently(30);
|
||||
value = AdbCommons.raw(serial, "getversion:");
|
||||
if (value != null) {
|
||||
this.put(FULL_VERSION, value);
|
||||
}
|
||||
ThreadUtils.sleepSilently(30);
|
||||
value = AdbCommons.raw(serial, "getsn:");
|
||||
if (value != null) {
|
||||
this.put(X_SERIAL_NUMBER, AdbUtils.parseSerialNumber(value));
|
||||
}
|
||||
ThreadUtils.sleepSilently(30);
|
||||
value = AdbCommons.raw(serial, "getcodebase:");
|
||||
if (value != null) {
|
||||
this.put(CODEBASE, value);
|
||||
}
|
||||
ThreadUtils.sleepSilently(30);
|
||||
value = AdbCommons.raw(serial, "getbranch:");
|
||||
if (value != null) {
|
||||
this.put(X_BRANCH, Branch.fromCode(value));
|
||||
}
|
||||
ThreadUtils.sleepSilently(30);
|
||||
value = AdbCommons.raw(serial, "getlanguage:");
|
||||
if (value != null) {
|
||||
this.put(LANGUAGE, value);
|
||||
}
|
||||
ThreadUtils.sleepSilently(30);
|
||||
value = AdbCommons.raw(serial, "getregion:");
|
||||
if (value != null) {
|
||||
this.put(REGION, value);
|
||||
}
|
||||
ThreadUtils.sleepSilently(30);
|
||||
value = AdbCommons.raw(serial, "getromzone:");
|
||||
if (value != null) {
|
||||
this.put(ROMZONE,value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class RecoveryProperties extends Properties {
|
||||
|
||||
@Override
|
||||
protected boolean parseInternal() {
|
||||
isTwrp();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void isTwrp(){
|
||||
if (YesNoMaybe.YES.equals(device.getAnswers().isInTwrpRecovery())){
|
||||
device.getAnswers().setAnswer(DeviceAnswers.HAS_TWRP, YesNoMaybe.YES);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public Object get(String key, Object defaultReturn){
|
||||
Object res = get(key);
|
||||
return res == null ? defaultReturn : res;
|
||||
}
|
||||
public Object get(String key){
|
||||
Object x = sideloadProperties.get(key);
|
||||
if (x == null){
|
||||
x = adbProperties.get(key);
|
||||
}
|
||||
if (x == null){
|
||||
x = fastbootProperties.get(key);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Properties adbProperties, fastbootProperties, sideloadProperties, recoveryProperties;
|
||||
private String serial;
|
||||
private Device device;
|
||||
|
||||
public DeviceProperties(Device device){
|
||||
this.device = device;
|
||||
this.serial = device.getSerial();
|
||||
adbProperties = new AdbProperties();
|
||||
fastbootProperties = new FastbootProperties();
|
||||
sideloadProperties = new SideloadProperties();
|
||||
recoveryProperties = new RecoveryProperties();
|
||||
}
|
||||
|
||||
public Properties getAdbProperties() {
|
||||
return adbProperties;
|
||||
}
|
||||
|
||||
public Properties getFastbootProperties() {
|
||||
return fastbootProperties;
|
||||
}
|
||||
|
||||
public Properties getSideloadProperties() {
|
||||
return sideloadProperties;
|
||||
}
|
||||
|
||||
public Properties getRecoveryProperties() {
|
||||
return recoveryProperties;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.xiaomitool.v2.adb.device;
|
||||
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.RunnableWithArg;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class Properties {
|
||||
private int failedParsingAttempts = 0;
|
||||
private final ConcurrentHashMap<String, Object> propertiesMap = new ConcurrentHashMap<String, Object>();
|
||||
private RunnableWithArg onFailedAttemptThree = null;
|
||||
private boolean parsed = false, failed = false;
|
||||
|
||||
public boolean isFailed() {
|
||||
return !parsed && failed;
|
||||
}
|
||||
|
||||
public boolean parse(){
|
||||
return parse(false);
|
||||
}
|
||||
public boolean parse(boolean force){
|
||||
|
||||
boolean res = parse(force, true);
|
||||
Log.debug("Parsing finished");
|
||||
return res;
|
||||
}
|
||||
public boolean parse(boolean force, boolean internal){
|
||||
synchronized (propertiesMap) {
|
||||
Log.debug("Starting parsing");
|
||||
if (parsed && !force) {
|
||||
return true;
|
||||
}
|
||||
parsed = true;
|
||||
if (parseInternal()) {
|
||||
Log.debug(this.toString());
|
||||
failedParsingAttempts = 0;
|
||||
return true;
|
||||
}
|
||||
failed = true;
|
||||
++failedParsingAttempts;
|
||||
if (failedParsingAttempts > 3) {
|
||||
Log.warn("Failed to parse properties for three times");
|
||||
if (onFailedAttemptThree != null) {
|
||||
onFailedAttemptThree.run(this);
|
||||
|
||||
}
|
||||
//failedParsingAttempts = 0;
|
||||
}
|
||||
parsed = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnFailedAttemptThree(RunnableWithArg onFailedAttemptThree) {
|
||||
this.onFailedAttemptThree = onFailedAttemptThree;
|
||||
}
|
||||
|
||||
public boolean isParsed() {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
protected abstract boolean parseInternal();
|
||||
public synchronized Object put(String key, Object value){
|
||||
synchronized (propertiesMap) {
|
||||
return propertiesMap.put(key, value);
|
||||
}
|
||||
}
|
||||
public synchronized Object get(String key){
|
||||
synchronized (propertiesMap) {
|
||||
return propertiesMap.get(key);
|
||||
}
|
||||
}
|
||||
public synchronized Object get(String key, Object defaultObject){
|
||||
synchronized (propertiesMap) {
|
||||
return propertiesMap.getOrDefault(key, defaultObject);
|
||||
}
|
||||
}
|
||||
public synchronized void putAll(Map<String, ?> map){
|
||||
synchronized (propertiesMap) {
|
||||
propertiesMap.putAll(map);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Map.Entry<String, Object> entry : propertiesMap.entrySet()){
|
||||
builder.append(entry.getKey()).append(" -> ").append(entry.getValue()).append(System.lineSeparator());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.xiaomitool.v2.crypto;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class AES {
|
||||
public static byte[] aes128cbc_encrypt(final byte[] key, final byte[] IV, final byte[] message) throws Exception {
|
||||
return aes128cbc_encryptDecrypt(Cipher.ENCRYPT_MODE, key, IV, message);
|
||||
}
|
||||
|
||||
public static byte[] aes128cbc_decrypt(final byte[] key, final byte[] IV, final byte[] message) throws Exception {
|
||||
return aes128cbc_encryptDecrypt(Cipher.DECRYPT_MODE, key, IV, message);
|
||||
}
|
||||
|
||||
private static byte[] aes128cbc_encryptDecrypt(final int mode, final byte[] key, final byte[] IV, final byte[] message) throws Exception {
|
||||
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
final SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
|
||||
final IvParameterSpec ivSpec = new IvParameterSpec(IV);
|
||||
cipher.init(mode, keySpec, ivSpec);
|
||||
return cipher.doFinal(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.xiaomitool.v2.crypto;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
public class Hash {
|
||||
public static String sha1Hex(String data){
|
||||
return DigestUtils.sha1Hex(data);
|
||||
}
|
||||
|
||||
public static String sha1Base64(String data){
|
||||
return Base64.encodeBase64String(DigestUtils.sha1(data));
|
||||
}
|
||||
|
||||
public static String md5Hex(String data){
|
||||
return DigestUtils.md5Hex(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.xiaomitool.v2.engine;
|
||||
|
||||
public class CommonsMessages {
|
||||
public static final int NOOP = -100;
|
||||
public static final int NO_MESSAGE = -1;
|
||||
public static final int DEVICE_UPDATE_STATUS = -2;
|
||||
public static final int NEW_DEVICE = -3;
|
||||
public static final int DEVICE_UPDATE_FINISH = -4;
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.xiaomitool.v2.engine;
|
||||
|
||||
import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.gui.controller.LoginController;
|
||||
import com.xiaomitool.v2.language.Lang;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.utils.MutexUtils;
|
||||
import com.xiaomitool.v2.utility.utils.SettingsUtils;
|
||||
import com.xiaomitool.v2.xiaomi.XiaomiKeystore;
|
||||
import javafx.application.Platform;
|
||||
import javafx.stage.Stage;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ToolManager {
|
||||
public static String TOOL_VERSION = "8.9.24";
|
||||
public static String URL_DONATION = "https://xiaomitool.page.link/donate";
|
||||
public static String TOOL_VERSION_EX = "unbrick only";
|
||||
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";
|
||||
private static boolean exiting = false;
|
||||
|
||||
|
||||
private static List<Stage> activeStages = new ArrayList<>();
|
||||
public static void init(Stage primaryStage) throws Exception {
|
||||
boolean isSingleInstance = MutexUtils.lock();
|
||||
if (!isSingleInstance){
|
||||
ToolManager.exit(1);
|
||||
return;
|
||||
}
|
||||
SettingsUtils.load();
|
||||
Lang.loadSystemLanguage();
|
||||
GuiUtils.init();
|
||||
checkLoadSession();
|
||||
|
||||
WindowManager.launchMain(primaryStage);
|
||||
}
|
||||
|
||||
public static void showStage(Stage stage){
|
||||
if (stage == null){
|
||||
return;
|
||||
}
|
||||
activeStages.add(stage);
|
||||
stage.show();
|
||||
}
|
||||
public static void closeStage(Stage stage){
|
||||
if (stage == null){
|
||||
return;
|
||||
}
|
||||
activeStages.remove(stage);
|
||||
stage.close();
|
||||
}
|
||||
public static void exit(int code){
|
||||
if (exiting){
|
||||
return;
|
||||
}
|
||||
exiting = true;
|
||||
saveOptions();
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
for (Stage stage : activeStages){
|
||||
stage.close();
|
||||
}
|
||||
MutexUtils.unlock();
|
||||
Log.closeLogFile();
|
||||
ToolManager.closeStage(WindowManager.mainWindow());
|
||||
System.exit(code);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
private static void saveOptions(){
|
||||
checkSaveSession();
|
||||
SettingsUtils.save();
|
||||
}
|
||||
private static void checkSaveSession(){
|
||||
String pcId = XiaomiKeystore.getInstance().getPcId();
|
||||
if (pcId != null){
|
||||
SettingsUtils.saveOpt(SettingsUtils.PC_ID, pcId);
|
||||
}
|
||||
String saveSession = SettingsUtils.getOpt(SettingsUtils.PREF_SAVE_SESSION);
|
||||
if (!"true".equals(saveSession)){
|
||||
SettingsUtils.saveOpt(SettingsUtils.SESSION_TOKEN,"null");
|
||||
return;
|
||||
}
|
||||
String json = XiaomiKeystore.getInstance().getJson();
|
||||
if (json == null){
|
||||
SettingsUtils.saveOpt(SettingsUtils.SESSION_TOKEN,"null");
|
||||
return;
|
||||
}
|
||||
SettingsUtils.saveOptEncrpyted(SettingsUtils.SESSION_TOKEN,json);
|
||||
}
|
||||
private static void checkLoadSession(){
|
||||
String pcId = SettingsUtils.getOpt(SettingsUtils.PC_ID);
|
||||
if (pcId != null){
|
||||
XiaomiKeystore.getInstance().setDeviceId(pcId);
|
||||
}
|
||||
String saveSession = SettingsUtils.getOpt(SettingsUtils.PREF_SAVE_SESSION);
|
||||
if (!"true".equals(saveSession)){
|
||||
return;
|
||||
}
|
||||
|
||||
String json = SettingsUtils.getOptDecrypted(SettingsUtils.SESSION_TOKEN);
|
||||
if (json == null){
|
||||
Log.warn("Failed to load old session token");
|
||||
return;
|
||||
}
|
||||
Log.debug("Old session token: "+json);
|
||||
try {
|
||||
JSONObject object = new JSONObject(json);
|
||||
XiaomiKeystore.getInstance().setCredentials(object);
|
||||
Log.debug(XiaomiKeystore.getInstance().getUserId());
|
||||
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LoginController.setLoginNumber(XiaomiKeystore.getInstance().getUserId());
|
||||
}
|
||||
});
|
||||
} catch (JSONException e){
|
||||
Log.warn("Failed to parse old session token: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.xiaomitool.v2.engine;
|
||||
|
||||
import com.xiaomitool.v2.engine.actions.ActionsStatic;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.RunnableMessage;
|
||||
import com.xiaomitool.v2.utility.WaitSemaphore;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class ToolRunner {
|
||||
private static int last_msg = 0;
|
||||
private static ExecutorService runner = Executors.newSingleThreadExecutor();
|
||||
private static WaitSemaphore semaphore = new WaitSemaphore();
|
||||
public static void run(RunnableMessage runnableMessage){
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
semaphore.setPermits(0);
|
||||
try {
|
||||
last_msg = runnableMessage.run();
|
||||
} catch (InterruptedException e) {
|
||||
Log.error("Executor runner thread interrutped :(");
|
||||
return;
|
||||
}
|
||||
semaphore.increase();
|
||||
}
|
||||
};
|
||||
runner.submit(runnable);
|
||||
}
|
||||
public static int runWait(RunnableMessage runnableMessage){
|
||||
run(runnableMessage);
|
||||
return waitMessage();
|
||||
}
|
||||
public static int waitMessage(){
|
||||
try {
|
||||
semaphore.waitOnce();
|
||||
} catch (InterruptedException e) {
|
||||
Log.error("Main tool runner thread interrutped :(");
|
||||
}
|
||||
return last_msg;
|
||||
}
|
||||
public static void start(){
|
||||
runner.submit(() -> {
|
||||
try {
|
||||
ActionsStatic.MAIN().run();
|
||||
} catch (InterruptedException e) {
|
||||
Log.error("Main tool runner thread interrutped :(");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,515 @@
|
||||
package com.xiaomitool.v2.engine.actions;
|
||||
|
||||
import com.xiaomitool.v2.adb.AdbException;
|
||||
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.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.gui.deviceView.DeviceView;
|
||||
import com.xiaomitool.v2.gui.drawable.DrawableManager;
|
||||
import com.xiaomitool.v2.gui.other.DeviceTableEntry;
|
||||
import com.xiaomitool.v2.gui.visual.*;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
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.install.GenericInstall;
|
||||
import com.xiaomitool.v2.procedure.uistuff.ChooseProcedure;
|
||||
import com.xiaomitool.v2.utility.Nullable;
|
||||
import com.xiaomitool.v2.utility.RunnableMessage;
|
||||
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.UnlockStatus;
|
||||
import javafx.animation.Animation;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextAlignment;
|
||||
|
||||
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());
|
||||
}
|
||||
public static RunnableMessage MAIN_SCREEN_LOADING(String message){
|
||||
return new RunnableMessage() {
|
||||
@Override
|
||||
public int run() throws InterruptedException {
|
||||
Node node = new LoadingAnimation.WithText(message,150);
|
||||
WindowManager.setMainContent(node,false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
public static RunnableMessage SEARCH_SELECT_DEVICES(@Nullable Device.Status wantedStatus){ return () -> {
|
||||
ActionsDynamic.MAIN_SCREEN_LOADING(LRes.SEARCHING_CONNECTED_DEVICES).run();
|
||||
DeviceManager.refresh();
|
||||
Thread.sleep(1000);
|
||||
int connectedDevices = DeviceManager.count(wantedStatus);
|
||||
RunnableMessage nextStep;
|
||||
if (connectedDevices == 0) {
|
||||
nextStep = NO_DEVICE_CONNECTED(wantedStatus);
|
||||
} else {
|
||||
nextStep = SELECT_DEVICE(wantedStatus);
|
||||
}
|
||||
return nextStep.run();
|
||||
};}
|
||||
|
||||
public static RunnableMessage NO_DEVICE_CONNECTED(@Nullable Device.Status wantedStatus) { return () -> {
|
||||
LRes msg, button;
|
||||
RunnableMessage howto = null;
|
||||
Device.Status wStatus = wantedStatus;
|
||||
if (wStatus == null){
|
||||
wStatus = Device.Status.DEVICE;
|
||||
}
|
||||
switch (wStatus){
|
||||
case SIDELOAD:
|
||||
case RECOVERY:
|
||||
msg = LRes.NO_DEVICE_CONNECTED_RECOVERY;
|
||||
button = LRes.HT_GO_RECOVERY;
|
||||
howto = ActionsStatic.HOWTO_GO_RECOVERY();
|
||||
break;
|
||||
case FASTBOOT:
|
||||
msg = LRes.NO_DEVICE_CONNECTED_FASTBOOT;
|
||||
button = LRes.HT_GO_FASTBOOT;
|
||||
break;
|
||||
default:
|
||||
msg = LRes.NO_DEVICE_CONNECTED;
|
||||
button = LRes.HT_ENABLE_USB_DEBUG;
|
||||
|
||||
}
|
||||
ButtonPane pane = new ButtonPane(LRes.SEARCH_AGAIN, button);
|
||||
ImageView no_connection = new ImageView(new Image(DrawableManager.getPng(DrawableManager.NO_CONNECTION).toString()));
|
||||
no_connection.setFitHeight(200);
|
||||
no_connection.setPreserveRatio(true);
|
||||
Text no = new Text(msg.toString());
|
||||
no.setTextAlignment(TextAlignment.CENTER);
|
||||
no.setFont(Font.font(16));
|
||||
VBox vBox = new VBox(no_connection,no);
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
vBox.setSpacing(20);
|
||||
pane.setContent(vBox);
|
||||
Log.debug("SDSDSASEW");
|
||||
WindowManager.setMainContent(pane);
|
||||
DeviceManager.addMessageReceiver(pane.getIdClickReceiver());
|
||||
int message = CommonsMessages.NOOP;
|
||||
while ((message != CommonsMessages.NEW_DEVICE || DeviceManager.count(wantedStatus) == 0) && message < 0){
|
||||
message=pane.waitClick();
|
||||
if (message > 0 && howto != null){
|
||||
message = howto.run();
|
||||
if (message >= 0){
|
||||
message = NOOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
DeviceManager.removeMessageReceiver(pane.getIdClickReceiver());
|
||||
|
||||
return ActionsDynamic.SEARCH_SELECT_DEVICES(wantedStatus).run();
|
||||
};}
|
||||
|
||||
public static RunnableMessage SELECT_DEVICE(@Nullable Device.Status wantedStatus) { return () -> {
|
||||
TableView<DeviceTableEntry> tableView = new TableView<DeviceTableEntry>(){
|
||||
public void requestFocus() { }
|
||||
};
|
||||
TableColumn<DeviceTableEntry,String> serial = new TableColumn<>(LRes.SERIAL.toString());
|
||||
TableColumn<DeviceTableEntry,String> status = new TableColumn<>(LRes.STATUS.toString());
|
||||
TableColumn<DeviceTableEntry,String> codename = new TableColumn<>(LRes.CODENAME.toString());
|
||||
TableColumn<DeviceTableEntry,String> brand = new TableColumn<>(LRes.BRAND.toString());
|
||||
TableColumn<DeviceTableEntry,String> model = new TableColumn<>(LRes.MODEL.toString());
|
||||
serial.setCellValueFactory(new PropertyValueFactory<>("serial"));
|
||||
status.setCellValueFactory(new PropertyValueFactory<>("status"));
|
||||
codename.setCellValueFactory(new PropertyValueFactory<>("codename"));
|
||||
brand.setCellValueFactory(new PropertyValueFactory<>("brand"));
|
||||
model.setCellValueFactory(new PropertyValueFactory<>("model"));
|
||||
tableView.getColumns().addAll(serial,status,codename,brand,model);
|
||||
ObservableList<DeviceTableEntry> observableList = tableView.getItems();
|
||||
for (Device device : DeviceManager.getDevices()){
|
||||
if (wantedStatus != null && !device.getStatus().equals(wantedStatus)){
|
||||
continue;
|
||||
}
|
||||
DeviceTableEntry tableEntry = new DeviceTableEntry(device);
|
||||
observableList.add(tableEntry);
|
||||
}
|
||||
tableView.getSelectionModel().select(0);
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.SELECT, LRes.SEARCH_AGAIN);
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
for (TableColumn column : tableView.getColumns()){
|
||||
column.setPrefWidth(120);
|
||||
column.setSortable(false);
|
||||
}
|
||||
|
||||
tableView.setPrefSize(600,400);
|
||||
tableView.setEditable(false);
|
||||
String hex = "ffa970";
|
||||
tableView.setStyle("-fx-focus-color: #C8C8C8;\n" +
|
||||
"-fx-faint-focus-color: #C8C8C8;\n" +
|
||||
"-fx-selection-bar: #"+hex+"; -fx-selection-bar-non-focused: #"+hex+";"
|
||||
);
|
||||
tableView.setBorder(Border.EMPTY);
|
||||
|
||||
|
||||
buttonPane.setContent(GuiUtils.center(tableView));
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
WindowManager.setMainContent(buttonPane);
|
||||
}
|
||||
});
|
||||
int message = CommonsMessages.NOOP;
|
||||
DeviceManager.addMessageReceiver(buttonPane.getIdClickReceiver());
|
||||
boolean newDevice = false;
|
||||
while (message == CommonsMessages.NOOP){
|
||||
message = buttonPane.waitClick();
|
||||
if (message == CommonsMessages.NEW_DEVICE){
|
||||
newDevice = true;
|
||||
} else if (newDevice && message == CommonsMessages.DEVICE_UPDATE_FINISH){
|
||||
observableList.clear();
|
||||
for (Device device : DeviceManager.getDevices()){
|
||||
if (wantedStatus != null && !device.getStatus().equals(wantedStatus)){
|
||||
continue;
|
||||
}
|
||||
DeviceTableEntry tableEntry = new DeviceTableEntry(device);
|
||||
observableList.add(tableEntry);
|
||||
|
||||
}
|
||||
tableView.getSelectionModel().select(0);
|
||||
newDevice = false;
|
||||
}
|
||||
if (message < 0){
|
||||
message = CommonsMessages.NOOP;
|
||||
}
|
||||
|
||||
if (message == 0){
|
||||
DeviceTableEntry selected = tableView.getSelectionModel().getSelectedItem();
|
||||
|
||||
if (selected == null){
|
||||
message = CommonsMessages.NOOP;
|
||||
} else {
|
||||
DeviceManager.setSelectedDevice(selected.getSerial());
|
||||
if (DeviceManager.getSelectedDevice() == null){
|
||||
message = CommonsMessages.NOOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return message == 0 ? 0 : SEARCH_SELECT_DEVICES(wantedStatus).run();
|
||||
};}
|
||||
|
||||
public static RunnableMessage REQUIRE_DEVICE_ON(Device device){
|
||||
return () -> {
|
||||
if (!device.isTurnedOn()){
|
||||
//Need to reboot to device
|
||||
REBOOT_DEVICE(device, Device.Status.DEVICE, false).run();
|
||||
WAIT_USB_DEBUG_ENABLE(device).run();
|
||||
}
|
||||
REQUIRE_DEVICE_AUTH(device).run();
|
||||
REQUIRE_DEVICE_CONNECTED(device).run();
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
public static RunnableMessage REQUIRE_DEVICE_CONNECTED(Device device){
|
||||
return () -> {
|
||||
if (device.isConnected()){
|
||||
return 0;
|
||||
}
|
||||
ButtonPane pane = new ButtonPane(LRes.TRY_AGAIN);
|
||||
ImageView no_connection = new ImageView(new Image(DrawableManager.getPng(DrawableManager.NO_CONNECTION).toString()));
|
||||
no_connection.setFitHeight(200);
|
||||
no_connection.setPreserveRatio(true);
|
||||
Text no = new Text(LRes.DEVICE_NOT_CONNECTED.toString());
|
||||
no.setTextAlignment(TextAlignment.CENTER);
|
||||
no.setFont(Font.font(16));
|
||||
no.setWrappingWidth(600);
|
||||
VBox vBox = new VBox(no_connection,no);
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
vBox.setSpacing(20);
|
||||
pane.setContent(vBox);
|
||||
WindowManager.setMainContent(pane);
|
||||
IDClickReceiver receiver = pane.getIdClickReceiver();
|
||||
DeviceManager.addMessageReceiver(receiver);
|
||||
int message = NOOP;
|
||||
while (message == NOOP){
|
||||
message = pane.waitClick();
|
||||
if (message == CommonsMessages.DEVICE_UPDATE_FINISH){
|
||||
if (device.isConnected()){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (message == 0){
|
||||
MAIN_SCREEN_LOADING(LRes.SEARCHING_CONNECTED_DEVICES).run();
|
||||
ActionsStatic.RESTART_ADB_SERVER().run();
|
||||
if (device.isConnected()){
|
||||
break;
|
||||
}
|
||||
WindowManager.removeTopContent();
|
||||
}
|
||||
message = NOOP;
|
||||
}
|
||||
DeviceManager.removeMessageReceiver(receiver);
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
public static RunnableMessage WAIT_USB_DEBUG_ENABLE(Device device){
|
||||
return WAIT_USB_DEBUG_ENABLE(device,null);
|
||||
}
|
||||
|
||||
public static RunnableMessage WAIT_USB_DEBUG_ENABLE(Device device, String text){
|
||||
return () -> {
|
||||
ButtonPane pane = new ButtonPane(LRes.HT_ENABLE_USB_DEBUG, LRes.SEARCH_AGAIN);
|
||||
WindowManager.setMainContent(pane);
|
||||
IDClickReceiver receiver = pane.getIdClickReceiver();
|
||||
DeviceManager.addMessageReceiver(receiver);
|
||||
int message = NOOP;
|
||||
while (message == NOOP){
|
||||
message = receiver.waitClick();
|
||||
if (message == CommonsMessages.DEVICE_UPDATE_FINISH){
|
||||
if (device.isTurnedOn()){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (message == 1){
|
||||
ActionsStatic.RESTART_ADB_SERVER().run();
|
||||
if (device.isTurnedOn()){
|
||||
break;
|
||||
}
|
||||
WindowManager.removeTopContent();
|
||||
|
||||
}
|
||||
|
||||
message = NOOP;
|
||||
|
||||
}
|
||||
DeviceManager.removeMessageReceiver(receiver);
|
||||
return 0;};
|
||||
}
|
||||
|
||||
public static RunnableMessage FIND_DEVICE_INFO(Device device){
|
||||
return () -> {
|
||||
Text texts[] = new Text[10];
|
||||
Text ktexts[] = new Text[10];
|
||||
LRes kstring[] = new LRes[]{LRes.SERIAL, LRes.BRAND, LRes.MODEL, LRes.CODENAME, LRes.MIUI_VERSION, LRes.ANDROID_VERSION, LRes.SERIAL_NUMBER, LRes.BOOTLOADER_STATUS, LRes.FASTBOOT_PARSED, LRes.RECOVERY_PARSED};
|
||||
for (int i = 0; i<kstring.length; ++i){
|
||||
texts[i] = new Text();
|
||||
ktexts[i] = new Text();
|
||||
texts[i].setFont(Font.font(14));
|
||||
ktexts[i].setFont(Font.font(14));
|
||||
ktexts[i].setText(kstring[i].toString()+" : ");
|
||||
}
|
||||
ActionsUtil.setDevicePropertiesText(device, texts);
|
||||
double width = WindowManager.getMainPane().getWidth()-100;
|
||||
RegularTable regularTable = new RegularTable(10,2,280,width);
|
||||
for (int i = 0; i<kstring.length; ++i){
|
||||
regularTable.add(ktexts[i],0,i,Pos.CENTER_RIGHT);
|
||||
regularTable.add(texts[i],1,i,Pos.CENTER_LEFT);
|
||||
}
|
||||
Text title = new Text(LRes.FINDING_INFO_TEXT.toString());
|
||||
title.setFont(Font.font(16));
|
||||
title.setWrappingWidth(width);
|
||||
title.setTextAlignment(TextAlignment.CENTER);
|
||||
|
||||
LoadingAnimation loadingAnimation = new LoadingAnimation(100);
|
||||
StackPane footer = new StackPane(loadingAnimation);
|
||||
footer.setPrefHeight(50);
|
||||
VBox vBox = new VBox(title, regularTable, footer);
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
vBox.setSpacing(10);
|
||||
|
||||
WindowManager.setMainContent(GuiUtils.center(vBox));
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!device.getDeviceProperties().getFastbootProperties().isParsed()) {
|
||||
try {
|
||||
if (!device.reboot(Device.Status.FASTBOOT)) {
|
||||
throw new Exception("Failed to reboot to fastboot");
|
||||
} else {
|
||||
|
||||
ActionsUtil.setDevicePropertiesText(device, texts);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
texts[8].setText(e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
ActionsUtil.setDevicePropertiesText(device, texts);
|
||||
}
|
||||
|
||||
if (!device.getDeviceProperties().getSideloadProperties().isParsed()) {
|
||||
try {
|
||||
if (UnlockStatus.UNLOCKED.equals(device.getAnswers().getUnlockStatus())) {
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
texts[9].setText(LRes.UNIMPORTANT.toString());
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
if (!device.reboot(Device.Status.RECOVERY)) {
|
||||
throw new Exception("Failed to reboot to recovery");
|
||||
} else {
|
||||
ActionsUtil.setDevicePropertiesText(device, texts);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
texts[9].setText(e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
ActionsUtil.setDevicePropertiesText(device, texts);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
ActionsDynamic.START_PROCEDURE(device).run();
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}).start();
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static RunnableMessage REQUIRE_DEVICE_AUTH(Device device){
|
||||
return () -> {
|
||||
if (!device.needAuthorization()){
|
||||
return 0;
|
||||
}
|
||||
ButtonPane pane = new ButtonPane( LRes.TRY_AGAIN);
|
||||
|
||||
IDClickReceiver receiver = pane.getIdClickReceiver();
|
||||
DeviceManager.addMessageReceiver(receiver);
|
||||
DeviceView deviceView = new DeviceView(DeviceView.DEVICE_18_9, 900);
|
||||
ImageView image = new ImageView(DrawableManager.getPng(DrawableManager.DEVICE_AUTH).toString());
|
||||
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);
|
||||
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.setAlignment(Pos.CENTER);
|
||||
vBox.setSpacing(20);
|
||||
|
||||
pane.setContent(vBox);
|
||||
|
||||
WindowManager.setMainContent(pane);
|
||||
|
||||
|
||||
int messsage = NOOP;
|
||||
while (messsage == NOOP){
|
||||
messsage = receiver.waitClick();
|
||||
if(messsage == CommonsMessages.DEVICE_UPDATE_FINISH){
|
||||
if (!device.needAuthorization()){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (messsage < 0){
|
||||
messsage = NOOP;
|
||||
}
|
||||
if (messsage == 0){
|
||||
DeviceManager.refresh();
|
||||
if (device.needAuthorization()) {
|
||||
ActionsStatic.RESTART_ADB_SERVER().run();
|
||||
if (!device.needAuthorization()){
|
||||
break;
|
||||
} else {
|
||||
WindowManager.setMainContent(pane);
|
||||
}
|
||||
}
|
||||
messsage = NOOP;
|
||||
}
|
||||
}
|
||||
DeviceManager.removeMessageReceiver(receiver);
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static RunnableMessage REBOOT_DEVICE(Device device, Device.Status status){
|
||||
return REBOOT_DEVICE(device,status,true); }
|
||||
|
||||
public static RunnableMessage REBOOT_DEVICE(Device device, Device.Status status, boolean wait){
|
||||
return () -> {
|
||||
try {
|
||||
boolean res = wait ? device.reboot(status) : device.rebootNoWait(status);
|
||||
} catch (AdbException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
public static RunnableMessage START_PROCEDURE(Device device){
|
||||
return new RunnableMessage() {
|
||||
@Override
|
||||
public int run() throws InterruptedException {
|
||||
InstallPane installPane = new InstallPane();
|
||||
WindowManager.setMainContent(installPane);
|
||||
ProcedureRunner runner = new ProcedureRunner(installPane.getListener());
|
||||
|
||||
|
||||
runner.init(null,device);
|
||||
|
||||
//runner.setContext("prop_"+DeviceProperties.CODENAME,"whyred");
|
||||
//FastbootFetch.findAllLatestFastboot().run(runner);
|
||||
try {
|
||||
Log.debug("PRO0 CHOOSE CAT");
|
||||
ChooseProcedure.chooseRomCategory().run(runner);
|
||||
Log.debug("PRO0 CHOOSE ROM");
|
||||
ChooseProcedure.chooseRom().run(runner);
|
||||
Log.debug("PRO0 FETCH RESOURCE");
|
||||
GenericInstall.resourceFetchWait().run(runner);
|
||||
Log.debug("PRO0 INSTALL ROM");
|
||||
GenericInstall.runInstallProcedure().run(runner);
|
||||
Log.debug("PRO0 FINISHED");
|
||||
GenericInstall.installationSuccess().run(runner);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
} catch (RMessage rMessage) {
|
||||
rMessage.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
package com.xiaomitool.v2.engine.actions;
|
||||
|
||||
import com.xiaomitool.v2.adb.AdbCommunication;
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.adb.device.DeviceManager;
|
||||
import com.xiaomitool.v2.engine.CommonsMessages;
|
||||
import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.PopupWindow;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
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.engine.ToolManager;
|
||||
import com.xiaomitool.v2.gui.raw.RawManager;
|
||||
import com.xiaomitool.v2.gui.visual.*;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.procedure.install.StockRecoveryInstall;
|
||||
import com.xiaomitool.v2.resources.ResourcesManager;
|
||||
import com.xiaomitool.v2.utility.DriverUtils;
|
||||
import com.xiaomitool.v2.utility.RunnableMessage;
|
||||
import com.xiaomitool.v2.utility.utils.InetUtils;
|
||||
import com.xiaomitool.v2.xiaomi.XiaomiKeystore;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextAlignment;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static com.xiaomitool.v2.engine.CommonsMessages.NOOP;
|
||||
import static com.xiaomitool.v2.engine.actions.ActionsDynamic.SEARCH_SELECT_DEVICES;
|
||||
import static com.xiaomitool.v2.engine.actions.ActionsDynamic.START_PROCEDURE;
|
||||
|
||||
|
||||
public class ActionsStatic {
|
||||
public static RunnableMessage MAIN() {
|
||||
return () -> {
|
||||
int message;
|
||||
message = FIRST_DISCLAIMER().run();
|
||||
if (message != 1) {
|
||||
ToolManager.exit(0);
|
||||
}
|
||||
CHECK_FOR_UPDATES().run();
|
||||
INSTALL_DRIVERS().run();
|
||||
return MOD_CHOOSE_SCREEN().run();
|
||||
};
|
||||
}
|
||||
public static RunnableMessage MOD_CHOOSE_SCREEN(){
|
||||
return () -> {
|
||||
RunnableMessage nextMain = MAIN_MOD_DEVICE();
|
||||
int message = NOOP;
|
||||
while (message == NOOP) {
|
||||
message = MOD_RECOVER_CHOICE().run();
|
||||
Log.debug("Choice: "+message);
|
||||
//TODO
|
||||
if (message == 1){
|
||||
message = FEATURE_NOT_AVAILABLE().run();
|
||||
}
|
||||
//ENDTODO
|
||||
nextMain = message == 0 ? MAIN_MOD_DEVICE() : MAIN_RECOVER_DEVICE();
|
||||
}
|
||||
return nextMain.run();
|
||||
};
|
||||
}
|
||||
|
||||
public static RunnableMessage INSTALL_DRIVERS(){
|
||||
return () -> {
|
||||
if (!SystemUtils.IS_OS_WINDOWS){
|
||||
return 0;
|
||||
}
|
||||
AdbCommunication.killServer();
|
||||
List<Path> driverPath;
|
||||
try {
|
||||
driverPath = ResourcesManager.getAllInfPaths();
|
||||
} catch (IOException e) {
|
||||
Log.error("Failed to find inf files: "+e.getMessage());
|
||||
return 1;
|
||||
}
|
||||
int totalFiles = driverPath.size();
|
||||
if(totalFiles == 0){
|
||||
return 1;
|
||||
}
|
||||
|
||||
LoadingAnimation.WithText loadingAnimation = new LoadingAnimation.WithText("",150);
|
||||
WindowManager.setMainContent(loadingAnimation, false);
|
||||
int i = 1;
|
||||
for (Path inf : driverPath){
|
||||
String fn = FilenameUtils.getName(inf.toString());
|
||||
loadingAnimation.setText(LRes.DRIVER_INSTALLING.toString(fn)+" ("+i+"/"+totalFiles+")");
|
||||
DriverUtils.installDriver(inf);
|
||||
++i;
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
DriverUtils.refresh();
|
||||
WindowManager.removeTopContent();
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
public static RunnableMessage MAIN_MOD_DEVICE() { return () -> {
|
||||
ActionsDynamic.MAIN_SCREEN_LOADING(LRes.SEARCHING_CONNECTED_DEVICES).run();
|
||||
AdbCommunication.restartServer();
|
||||
AdbCommunication.registerAutoScanDevices();
|
||||
ActionsDynamic.SEARCH_SELECT_DEVICES(null).run();
|
||||
Log.debug("SEARCHING");
|
||||
ActionsDynamic.REQUIRE_DEVICE_ON(DeviceManager.getSelectedDevice()).run();
|
||||
ActionsDynamic.FIND_DEVICE_INFO(DeviceManager.getSelectedDevice()).run();
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
public static RunnableMessage FEATURE_NOT_AVAILABLE(){
|
||||
return () -> {
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
WindowManager.launchPopup(new PopupWindow.ImageTextPopup(LRes.FEATURE_NOT_AVAILABLE.toString(), PopupWindow.Icon.INFO));
|
||||
}
|
||||
});
|
||||
|
||||
return NOOP;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static RunnableMessage RESTART_ADB_SERVER(){
|
||||
return () -> {
|
||||
ActionsDynamic.MAIN_SCREEN_LOADING(LRes.LOADING).run();
|
||||
AdbCommunication.restartServer();
|
||||
DeviceManager.refresh();
|
||||
WindowManager.removeTopContent();
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static RunnableMessage MAIN_RECOVER_DEVICE () { return () -> {
|
||||
//TODO
|
||||
return MAIN_RECOVER_DEVICE_TMP().run();
|
||||
};}
|
||||
|
||||
public static RunnableMessage MAIN_RECOVER_DEVICE_TMP(){
|
||||
return () -> {
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.OK_UNDERSTAND);
|
||||
Text instruction = new Text(LRes.RECOVERY_RECOVER_TMP.toString());
|
||||
instruction.setFont(Font.font(15));
|
||||
// instruction.setTextAlignment(TextAlignment.CENTER);
|
||||
instruction.setWrappingWidth(WindowManager.getMainPane().getWidth()-180);
|
||||
buttonPane.setContent(instruction);
|
||||
WindowManager.setMainContent(buttonPane);
|
||||
buttonPane.waitClick();
|
||||
ActionsDynamic.MAIN_SCREEN_LOADING(LRes.LOADING).run();
|
||||
AdbCommunication.restartServer();
|
||||
AdbCommunication.registerAutoScanDevices();
|
||||
Thread.sleep(500);
|
||||
|
||||
|
||||
SEARCH_SELECT_DEVICES(Device.Status.SIDELOAD).run();
|
||||
// START_PROCEDURE(StockRecoveryInstall.recoverStuckDevice()).run();
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
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 () -> {
|
||||
ActionsDynamic.MAIN_SCREEN_LOADING(LRes.LOADING).run();
|
||||
boolean connected = InetUtils.isInternetAvailable();
|
||||
if (connected){
|
||||
return NOOP;
|
||||
}
|
||||
ErrorPane errorPane = new ErrorPane(LRes.TRY_AGAIN);
|
||||
errorPane.setTitle(LRes.INET_CONNECTION_ERROR_TITLE);
|
||||
errorPane.setText(LRes.INET_CONNECTION_ERROR_TEXT);
|
||||
|
||||
while (!connected) {
|
||||
WindowManager.setMainContent(errorPane,false);
|
||||
errorPane.waitClick();
|
||||
WindowManager.removeTopContent();
|
||||
Thread.sleep(1000);
|
||||
connected = InetUtils.isInternetAvailable();
|
||||
|
||||
}
|
||||
|
||||
return NOOP;
|
||||
};
|
||||
}
|
||||
public static RunnableMessage CHECK_FOR_UPDATES(){
|
||||
return () -> {
|
||||
ActionsStatic.REQUIRE_INTERNET_CONNECTION().run();
|
||||
int res = InetUtils.checkForUpdates(ToolManager.URL_UPDATE, ToolManager.TOOL_VERSION, XiaomiKeystore.getInstance().getHashedPcId());
|
||||
if (res == 0){
|
||||
Log.info("Tool is updated, check version: "+ToolManager.TOOL_VERSION);
|
||||
return 0;
|
||||
} else if (res != 1){
|
||||
Log.warn("Failed to check for updates, error code: "+res);
|
||||
return -1;
|
||||
}
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.IGNORE, LRes.UPDATE_WILL_UPDATE);
|
||||
buttonPane.setContentText(LRes.UPDATE_AVAILABLE_TEXT);
|
||||
WindowManager.setMainContent(buttonPane,false);
|
||||
int msg = buttonPane.waitClick();
|
||||
if (msg == 1){
|
||||
InetUtils.openUrlInBrowser(ToolManager.URL_LATEST);
|
||||
ToolManager.exit(1);
|
||||
}
|
||||
WindowManager.removeTopContent();
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static RunnableMessage FIRST_DISCLAIMER() { return () -> {
|
||||
ButtonPane buttonPane = new ButtonPane(LRes.DONT_AGREE.toString(),LRes.AGREE.toString());
|
||||
Text t2 = new Text(RawManager.getDisclaimer());
|
||||
t2.setFont(Font.font(15));
|
||||
Pane p = new TextScrollPane( t2, LRes.DISCLAIMER.toString());
|
||||
p.setPadding(new Insets(20,100,20,100));
|
||||
buttonPane.setContent(p);
|
||||
WindowManager.setMainContent(buttonPane);
|
||||
Log.debug(Thread.currentThread());
|
||||
return buttonPane.waitClick();
|
||||
};}
|
||||
public static RunnableMessage MOD_RECOVER_CHOICE() { return () -> {
|
||||
IDClickReceiver idClickReceiver = new IDClickReceiver();
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
double height = WindowManager.getMainPane().getHeight()*2/3;
|
||||
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));
|
||||
running.setContent(DrawableManager.getPng(DrawableManager.MIUI10));
|
||||
Button b1 = new CustomButton(LRes.CHOOSE);
|
||||
Button b2 = new CustomButton(LRes.CHOOSE);
|
||||
b1.setMinWidth(100);
|
||||
b1.setFont(Font.font(14));
|
||||
b2.setMinWidth(100);
|
||||
b2.setFont(Font.font(14));
|
||||
Text t2 = new Text(LRes.CHOOSE_RECOVER_DEVICE.toString());
|
||||
Text t1 = new Text(LRes.CHOOSE_MOD_DEVICE.toString());
|
||||
t1.setFont(Font.font(14));
|
||||
t2.setFont(Font.font(14));
|
||||
t1.setTextAlignment(TextAlignment.CENTER);
|
||||
t2.setTextAlignment(TextAlignment.CENTER);
|
||||
VBox vBox1 = new VBox(GuiUtils.center(running), t1, b1);
|
||||
VBox vBox2 = new VBox(GuiUtils.center(recover), t2, b2);
|
||||
idClickReceiver.addNodes(b1,b2,running.getImagePane(),recover.getImagePane());
|
||||
vBox1.setAlignment(Pos.CENTER);
|
||||
vBox2.setAlignment(Pos.CENTER);
|
||||
HBox hBox = new HBox(vBox1, vBox2);
|
||||
hBox.setAlignment(Pos.CENTER);
|
||||
|
||||
hBox.setSpacing(100);
|
||||
vBox1.setSpacing(20);
|
||||
vBox2.setSpacing(20);
|
||||
WindowManager.setMainContent(hBox);
|
||||
}
|
||||
});
|
||||
return idClickReceiver.waitClick()%2;
|
||||
};}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.xiaomitool.v2.engine.actions;
|
||||
|
||||
import com.xiaomitool.v2.adb.device.Device;
|
||||
import com.xiaomitool.v2.adb.device.DeviceProperties;
|
||||
import com.xiaomitool.v2.adb.device.Properties;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.utility.utils.NumberUtils;
|
||||
import com.xiaomitool.v2.xiaomi.miuithings.UnlockStatus;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.text.Text;
|
||||
|
||||
public class ActionsUtil {
|
||||
public static void setDevicePropertiesText(Device device, Text... texts){
|
||||
if (!Platform.isFxApplicationThread()){
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setDevicePropertiesText(device, texts);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (texts.length < 10){
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceProperties props = device.getDeviceProperties();
|
||||
String brand, codename, model, serial, bootStatus, miuiVersion, androidVersion, recoveryAvailable, fastbootAvailable, serialNumber;
|
||||
brand = props.get(DeviceProperties.BRAND, LRes.UNKNOWN).toString();
|
||||
codename = props.get(DeviceProperties.CODENAME, LRes.UNKNOWN).toString();
|
||||
model = props.get(DeviceProperties.MODEL, LRes.UNKNOWN).toString();
|
||||
serial = device.getSerial();
|
||||
UnlockStatus unlockStatus = (UnlockStatus) props.get(DeviceProperties.X_LOCKSTATUS);
|
||||
bootStatus = (UnlockStatus.UNLOCKED.equals(unlockStatus) ? LRes.UNLOCKED : (UnlockStatus.LOCKED.equals(unlockStatus) ? LRes.LOCKED : LRes.UNKNOWN)).toString();
|
||||
miuiVersion = props.get(DeviceProperties.FULL_VERSION, LRes.UNKNOWN).toString();
|
||||
androidVersion = props.get(DeviceProperties.CODEBASE, LRes.UNKNOWN).toString();
|
||||
Properties sideloadProperties =props.getSideloadProperties();
|
||||
recoveryAvailable = !UnlockStatus.UNLOCKED.equals(unlockStatus) ? (sideloadProperties.isParsed() ? LRes.YES : (sideloadProperties.isFailed() ? LRes.NO : LRes.UNKNOWN)).toString() : LRes.IRRELEVANT.toString() ;
|
||||
Properties fastbootProperties =props.getFastbootProperties();
|
||||
fastbootAvailable = fastbootProperties.isParsed() ? LRes.YES.toString() : (fastbootProperties.isFailed() ? LRes.NO.toString() : LRes.UNKNOWN.toString()) ;
|
||||
int sn = (Integer) props.get(DeviceProperties.X_SERIAL_NUMBER,0);
|
||||
serialNumber = sn != 0 ? NumberUtils.intToHex(sn) : LRes.UNKNOWN.toString();
|
||||
texts[0].setText(serial);
|
||||
texts[1].setText(brand);
|
||||
texts[2].setText(model);
|
||||
texts[3].setText(codename);
|
||||
texts[4].setText(miuiVersion);
|
||||
texts[5].setText(androidVersion);
|
||||
texts[6].setText(serialNumber);
|
||||
texts[7].setText(bootStatus);
|
||||
texts[8].setText(fastbootAvailable);
|
||||
texts[9].setText(recoveryAvailable);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.xiaomitool.v2.gui;
|
||||
|
||||
import javafx.scene.Node;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class GuiObjects extends HashMap<String, Node> {
|
||||
private static final GuiObjects instance = new GuiObjects();
|
||||
|
||||
public static final String LOGIN_LINK = "login_link";
|
||||
public static final String LOGIN_NUMBER ="login_number";
|
||||
public static final String TRANSLATED_LINK = "translated_link";
|
||||
public static final String IMG_CLOSE = "img_close";
|
||||
public static final String IMG_MINIFY = "img_minify";
|
||||
public static final String IMG_SETTINGS = "img_settings";
|
||||
|
||||
public static Node getNode(String name){
|
||||
return instance.get(name);
|
||||
}
|
||||
public static void set(String name, Node node){
|
||||
instance.put(name,node);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.xiaomitool.v2.gui;
|
||||
|
||||
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.NotNull;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Bounds;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class GuiUtils {
|
||||
private static ExecutorService guiWaitThread = Executors.newSingleThreadExecutor();
|
||||
public static Background backgroundFromColor(Paint paint){
|
||||
return new Background(new BackgroundFill(paint,null,null));
|
||||
}
|
||||
|
||||
public static void init(){
|
||||
Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA);
|
||||
}
|
||||
|
||||
public static void setViewportChange(ImageView image, GetViewport func){
|
||||
image.setOnMouseEntered(event -> {
|
||||
if (!func.isPressed) {
|
||||
image.setViewport(func.get(1));
|
||||
}
|
||||
func.isHover = true;
|
||||
//Log.debug("MouseEnter");
|
||||
});
|
||||
image.setOnMouseExited(event -> {
|
||||
if (!func.isPressed) {
|
||||
image.setViewport(func.get(0));
|
||||
}
|
||||
func.isHover = false;
|
||||
//Log.debug("MouseExit");
|
||||
});
|
||||
image.setOnMousePressed(event -> {
|
||||
image.setViewport(func.get(2));
|
||||
func.isPressed = true;
|
||||
//Log.debug("MousePress");
|
||||
});
|
||||
image.setOnMouseReleased(event -> {
|
||||
image.setViewport(func.get(func.isHover ? 1 : 0));
|
||||
func.isPressed = false;
|
||||
//Log.debug("MouseRelease");
|
||||
});
|
||||
}
|
||||
|
||||
public static abstract class GetViewport {
|
||||
public boolean isPressed = false, isHover = false;
|
||||
public abstract Rectangle2D get(int index);
|
||||
|
||||
}
|
||||
public static Pane center(Node node){
|
||||
HBox hBox = new HBox(node);
|
||||
VBox vBox = new VBox(hBox);
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
hBox.setAlignment(Pos.CENTER);
|
||||
return vBox;
|
||||
}
|
||||
public static void waitGui(long millis, Runnable runnable){
|
||||
Runnable runnable1 = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
Log.warn("Thread interrupted :(");
|
||||
}
|
||||
Platform.runLater(runnable);
|
||||
}
|
||||
};
|
||||
guiWaitThread.submit(runnable1);
|
||||
}
|
||||
public static void tooltip(Node node, LRes key){
|
||||
tooltip(node, key.toString());
|
||||
}
|
||||
public static void tooltip(Node node, String text){
|
||||
Tooltip.install(node,new Tooltip(text));
|
||||
}
|
||||
public static Pane debug(Pane pane){
|
||||
debug(pane,Color.ALICEBLUE);
|
||||
return pane;
|
||||
}
|
||||
public static Pane debug(Pane pane, Color color){
|
||||
pane.setBackground(backgroundFromColor(color));
|
||||
return pane;
|
||||
}
|
||||
public static Pane crop(Pane pane, double x, double y, double width, double height){
|
||||
pane.setLayoutY(-1*y);
|
||||
pane.setLayoutX(-1*x);
|
||||
Pane pane1 = new Pane(pane);
|
||||
pane1.setClip(new Rectangle(width,height));
|
||||
pane1.setPrefSize(width,height);
|
||||
pane1.setMaxSize(width,height);
|
||||
return pane1;
|
||||
}
|
||||
public static boolean hasParent(Node node, Parent parent){
|
||||
Parent p = node.getParent();
|
||||
while (p != null){
|
||||
if (p == parent){
|
||||
return true;
|
||||
}
|
||||
p = p.getParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static double distanceBetween(@NotNull Node node1,@NotNull Node node2) {
|
||||
if (node2 == null) {
|
||||
return -1;
|
||||
}
|
||||
double center[] = getCenterCoordinates(node2);
|
||||
if (center == null){
|
||||
return -1;
|
||||
}
|
||||
return distanceBetween(node1, center[0],center[1]);
|
||||
|
||||
}
|
||||
public static double distanceBetween(@NotNull Node node1, double x, double y){
|
||||
if (node1 == null) {
|
||||
return -1;
|
||||
}
|
||||
double center[] = getCenterCoordinates(node1);
|
||||
if (center == null){
|
||||
return -1;
|
||||
}
|
||||
return distanceBetween(center[0],center[1],x,y);
|
||||
}
|
||||
|
||||
public static double distanceBetween(double x1, double y1, double x2, double y2){
|
||||
return Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
|
||||
}
|
||||
public static double[] getCenterCoordinates(@NotNull Node node){
|
||||
if (node == null || node.getBoundsInLocal() == null) {
|
||||
return null;
|
||||
}
|
||||
Bounds sceneBounds = node.localToScene(node.getBoundsInLocal());
|
||||
double centerX1 = (sceneBounds.getMinX() + sceneBounds.getMaxX()) / 2, centerY1 = (sceneBounds.getMinY() + sceneBounds.getMaxY()) / 2;
|
||||
if ( centerX1 <= 0 || centerY1 <= 0) {
|
||||
return null;
|
||||
}
|
||||
return new double[]{centerX1,centerY1};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.xiaomitool.v2.gui;
|
||||
|
||||
import com.xiaomitool.v2.engine.ToolManager;
|
||||
import javafx.application.Application;
|
||||
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class MainWindow extends Application {
|
||||
private static final String FXML_FILE = "MainFrame.fxml";
|
||||
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
|
||||
ToolManager.init(primaryStage);
|
||||
/*
|
||||
FXMLLoader loader = new FXMLLoader(FxmlManager.getFxml(FXML_FILE));
|
||||
loader.setController(new MainWindowController(primaryStage));
|
||||
Parent root = loader.load();
|
||||
Scene scene = new Scene(root);
|
||||
primaryStage.initStyle(StageStyle.UNDECORATED);
|
||||
primaryStage.setScene(scene);
|
||||
primaryStage.show();*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.xiaomitool.v2.gui;
|
||||
|
||||
import com.xiaomitool.v2.gui.drawable.DrawableManager;
|
||||
|
||||
import com.xiaomitool.v2.utility.Nullable;
|
||||
import javafx.geometry.Bounds;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public class PopupWindow {
|
||||
private double width, height;
|
||||
private Node content;
|
||||
public PopupWindow(){
|
||||
this(200,100);
|
||||
}
|
||||
|
||||
public void setHeight(double height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public void setWidth(double width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public PopupWindow(double width, double height){
|
||||
this.width =width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public void setContent(Node content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Node getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public double getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public static class ImageTextPopup extends PopupWindow {
|
||||
private static final double IMG_HEIGHT = 40;
|
||||
|
||||
public ImageTextPopup(String text, Icon icon){
|
||||
this(text,icon,null,null);
|
||||
}
|
||||
|
||||
public ImageTextPopup(String text, Icon icon, @Nullable Double fontSize, @Nullable Double width) { ;
|
||||
Text t = new Text(text);
|
||||
if (width == null || width == 0){
|
||||
width = 300d;
|
||||
}
|
||||
if (fontSize == null || fontSize == 0){
|
||||
fontSize = 15d;
|
||||
}
|
||||
t.setFont(Font.font(fontSize));
|
||||
double origWidth = t.getLayoutBounds().getWidth();
|
||||
if (origWidth > 0 && origWidth/width < 2){
|
||||
width = origWidth;
|
||||
}
|
||||
|
||||
t.setWrappingWidth(width);
|
||||
Bounds box = t.getLayoutBounds();
|
||||
if (4*box.getHeight() > 3*box.getWidth()){
|
||||
width = Math.sqrt(box.getHeight()*box.getWidth()*4/3);
|
||||
t.setWrappingWidth(width);
|
||||
width = t.getLayoutBounds().getWidth();
|
||||
}
|
||||
double height = t.getLayoutBounds().getHeight();
|
||||
if (height < IMG_HEIGHT+20){height=IMG_HEIGHT+20;}
|
||||
ImageView imageView = new ImageView(new Image(icon.getPng()));
|
||||
imageView.setFitHeight(IMG_HEIGHT);
|
||||
imageView.setPreserveRatio(true);
|
||||
StackPane imgPane = new StackPane(imageView);
|
||||
|
||||
HBox hBox = new HBox(imgPane, new StackPane(t));
|
||||
hBox.setSpacing(10);
|
||||
hBox.setAlignment(Pos.CENTER);
|
||||
width = width+20+20+IMG_HEIGHT;
|
||||
setHeight(height+50);
|
||||
setWidth(width);
|
||||
setContent(hBox);
|
||||
}
|
||||
}
|
||||
|
||||
public enum Icon {
|
||||
INFO("info.png"),
|
||||
WARN("caution.png"),
|
||||
ERROR("error.png");
|
||||
private URL png;
|
||||
Icon(String png){
|
||||
this.png = DrawableManager.getPng(png);
|
||||
}
|
||||
public String getPng() {
|
||||
return png.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
package com.xiaomitool.v2.gui;
|
||||
|
||||
import com.xiaomitool.v2.gui.controller.*;
|
||||
import com.xiaomitool.v2.gui.drawable.DrawableManager;
|
||||
import com.xiaomitool.v2.gui.fxml.FxmlManager;
|
||||
import com.xiaomitool.v2.engine.ToolManager;
|
||||
import com.xiaomitool.v2.gui.visual.OverlayPane;
|
||||
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 javafx.application.Platform;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.effect.DropShadow;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class WindowManager {
|
||||
public static final Color XIAOMI_COLOR = Color.rgb(255,103, 0);
|
||||
public static final String XIAOMI_COLOR_HEX = "FF6700";
|
||||
public static final Color DEFAULT_BACKGROUND_COLOR = Color.rgb(245,245,245);
|
||||
public static final Background DEFAULT_BACKGROUND = new Background(new BackgroundFill(DEFAULT_BACKGROUND_COLOR, null, null));
|
||||
public static final String FRAME_LOGIN = "LoginFrame";
|
||||
public static final String FRAME_MAIN = "MainFrame";
|
||||
public static final String FRAME_SETTINGS = "SettingsFrame";
|
||||
private static final String FRAME_POPUP = "Popup";
|
||||
private static final String DEFAULT_TITLE = "XiaoMiTool V2";
|
||||
public static final double PREF_WIN_WIDTH = 860;
|
||||
public static final double PREF_WIN_HEIGHT = 860;
|
||||
private static final URL iconUri = DrawableManager.getPng("icon.png");
|
||||
private static Stage mainStage;
|
||||
private static ToastPane toastPane;
|
||||
private static OverlayPane mainOverlay;
|
||||
private static VisiblePane mainVisiblePane;
|
||||
private static final DropShadow windowDropShadow = new DropShadow(10, 1, 1, Color.gray(0.7));
|
||||
|
||||
public static void setMainVisiblePane(VisiblePane pane){
|
||||
|
||||
|
||||
mainVisiblePane = pane;
|
||||
mainVisiblePane.getPane().setMaxSize(PREF_WIN_WIDTH, PREF_WIN_HEIGHT-90);
|
||||
}
|
||||
public static void setMainContent(Node node){
|
||||
setMainContent(node,true);
|
||||
}
|
||||
public static void removeTopContent(){
|
||||
if (mainVisiblePane == null){
|
||||
return;
|
||||
}
|
||||
if (Platform.isFxApplicationThread()) {
|
||||
mainVisiblePane.removeTop();
|
||||
} else {
|
||||
Platform.runLater(WindowManager::removeTopContent);
|
||||
}
|
||||
}
|
||||
public static void setMainContent(Node node, boolean deleteUnder){
|
||||
if (mainVisiblePane == null){
|
||||
return;
|
||||
}
|
||||
if (Platform.isFxApplicationThread()) {
|
||||
mainVisiblePane.add(node);
|
||||
} else {
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mainVisiblePane.saveStack(!deleteUnder);
|
||||
mainVisiblePane.add(node);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void hotKey(){
|
||||
mainStage.getScene().setOnKeyPressed(new EventHandler<KeyEvent>() {
|
||||
@Override
|
||||
public void handle(KeyEvent event) {
|
||||
Log.info(event.getCode().getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static double getContentHeight(){
|
||||
if (mainVisiblePane != null && mainVisiblePane.getPane() != null && mainVisiblePane.getPane().getHeight() > 0){
|
||||
return mainVisiblePane.getPane().getHeight();
|
||||
}
|
||||
return PREF_WIN_HEIGHT-100;
|
||||
}
|
||||
public static double getContentWidth(){
|
||||
if (mainVisiblePane != null && mainVisiblePane.getPane() != null && mainVisiblePane.getPane().getWidth() > 0){
|
||||
return mainVisiblePane.getPane().getWidth();
|
||||
}
|
||||
return PREF_WIN_WIDTH;
|
||||
}
|
||||
public static Stage getMainStage(){
|
||||
return mainStage;
|
||||
}
|
||||
|
||||
|
||||
public static Pane getMainPane(){
|
||||
return mainVisiblePane.getPane();
|
||||
}
|
||||
|
||||
public static Stage mainWindow(){
|
||||
return mainStage;
|
||||
}
|
||||
|
||||
public static Stage launchSettings(){
|
||||
return launchWindow(FRAME_SETTINGS,new SettingsController());
|
||||
}
|
||||
|
||||
|
||||
public static Stage launchLogin(){
|
||||
return launchWindow(FRAME_LOGIN, new LoginController());
|
||||
}
|
||||
public static void launchMain(Stage primaryStage){
|
||||
mainStage = primaryStage;
|
||||
launchWindow(FRAME_MAIN, new MainWindowController(),primaryStage);
|
||||
primaryStage.setOnCloseRequest(event -> {
|
||||
ToolManager.exit(0);
|
||||
// Save file
|
||||
});
|
||||
//hotKey();
|
||||
}
|
||||
public static Stage launchWindow(String fxml, DefaultController controller){
|
||||
return launchWindow(fxml,controller,null);
|
||||
}
|
||||
public static void toast(String message){
|
||||
if (toastPane == null){
|
||||
Log.warn("Cannot toast message: "+message);
|
||||
return;
|
||||
}
|
||||
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());
|
||||
|
||||
stage.setTitle(DEFAULT_TITLE);
|
||||
stage.sizeToScene();
|
||||
centerStage(stage);
|
||||
return stage;
|
||||
|
||||
}
|
||||
private static Stage launchWindow(String fxml, DefaultController controller, Stage primaryStage){
|
||||
return launchWindow(fxml,controller,primaryStage,null);
|
||||
}
|
||||
private static void centerStage(Stage stage){
|
||||
|
||||
double x = mainStage.getX()+(mainStage.getWidth()-stage.getWidth())/2;
|
||||
double y = mainStage.getY()+(mainStage.getHeight()-stage.getHeight())/2;
|
||||
stage.setX(x);
|
||||
stage.setY(y);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static Stage launchWindow(String fxml, DefaultController controller, Stage primaryStage, Pointer pointer) {
|
||||
boolean isMain = primaryStage == mainStage && primaryStage != null;
|
||||
if (isMain){
|
||||
Log.info("Launching main window");
|
||||
}
|
||||
primaryStage = primaryStage != null ? primaryStage : new Stage();
|
||||
FXMLLoader loader = new FXMLLoader(FxmlManager.getFxml(fxml));
|
||||
controller.setPrimaryStage(primaryStage);
|
||||
loader.setController(controller);
|
||||
Parent root = null;
|
||||
Object realRoot = null;
|
||||
try {
|
||||
root = loader.load();
|
||||
} catch (IOException e) {
|
||||
Log.error("Failed to load "+fxml+" fxml resource: "+e.getMessage());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Background background = DEFAULT_BACKGROUND;
|
||||
if (pointer != null) {
|
||||
pointer.pointed = root;
|
||||
}
|
||||
if (root instanceof Pane){
|
||||
((Pane) root).setBackground(background);
|
||||
if (isMain){
|
||||
mainOverlay = new OverlayPane();
|
||||
toastPane = new ToastPane(mainOverlay, 300,20,10,100,1500);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
background = null;
|
||||
}
|
||||
Scene scene;
|
||||
realRoot = (Parent) root;
|
||||
if (background != null) {
|
||||
Log.debug("Dropping shadow on: "+root);
|
||||
StackPane pane = new StackPane(root);
|
||||
if (isMain){
|
||||
pane.getChildren().add(mainOverlay);
|
||||
|
||||
}
|
||||
pane.setStyle("-fx-background-color: rgba(0, 0, 0, 0.0);");
|
||||
root.setEffect(windowDropShadow);
|
||||
Log.debug(root.getEffect());
|
||||
pane.setPadding(new Insets(10));
|
||||
realRoot = pane;
|
||||
}
|
||||
|
||||
scene = new Scene((Parent) realRoot);
|
||||
primaryStage.getIcons().add(new Image(iconUri.toString()));
|
||||
primaryStage.setTitle(DEFAULT_TITLE);
|
||||
|
||||
scene.setFill(Color.TRANSPARENT);
|
||||
if (!isMain){
|
||||
primaryStage.initModality(Modality.APPLICATION_MODAL);
|
||||
primaryStage.initOwner(mainStage);
|
||||
}
|
||||
primaryStage.initStyle(StageStyle.UNDECORATED);
|
||||
primaryStage.initStyle(StageStyle.TRANSPARENT);
|
||||
|
||||
primaryStage.setScene(scene);
|
||||
Log.debug(primaryStage.getWidth());
|
||||
ToolManager.showStage(primaryStage);
|
||||
if (!isMain){
|
||||
centerStage(primaryStage);
|
||||
}
|
||||
return primaryStage;
|
||||
}
|
||||
|
||||
public static void runNowOrLater(Runnable runnable) {
|
||||
if (Platform.isFxApplicationThread()){
|
||||
runnable.run();
|
||||
} else {
|
||||
Platform.runLater(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
public static void popup(String string, PopupWindow.Icon icon) {
|
||||
runNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PopupWindow popupWindow = new PopupWindow.ImageTextPopup(string,icon);
|
||||
launchPopup(popupWindow);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.xiaomitool.v2.gui.controller;
|
||||
|
||||
import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.engine.ToolManager;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public abstract class DefaultController {
|
||||
public DefaultController(){}
|
||||
public DefaultController(Stage primaryStage){
|
||||
this.primaryStage = primaryStage;
|
||||
}
|
||||
protected Stage primaryStage;
|
||||
private double stageX, stageY;
|
||||
|
||||
|
||||
protected void initHeaderDrag(Node HEADER){
|
||||
HEADER.setOnMousePressed(event -> {
|
||||
HEADER.setCursor(Cursor.CLOSED_HAND);
|
||||
stageX = event.getSceneX();
|
||||
stageY = event.getSceneY();
|
||||
});
|
||||
HEADER.setOnMouseReleased(event -> {
|
||||
HEADER.setCursor(Cursor.DEFAULT);
|
||||
stageX = event.getSceneX();
|
||||
stageY = event.getSceneY();
|
||||
});
|
||||
HEADER.setOnMouseDragged(event -> {
|
||||
primaryStage.setX(event.getScreenX() - stageX);
|
||||
primaryStage.setY(event.getScreenY() - stageY);
|
||||
});
|
||||
}
|
||||
|
||||
public void setPrimaryStage(Stage primaryStage) {
|
||||
this.primaryStage = primaryStage;
|
||||
}
|
||||
|
||||
protected void setCloseImage(ImageView IMG_CLOSE){
|
||||
setCloseImage(IMG_CLOSE, false);
|
||||
}
|
||||
protected void setCloseImage(ImageView IMG_CLOSE, boolean exit){
|
||||
IMG_CLOSE.setOnMouseClicked(event -> {
|
||||
if (exit) {
|
||||
ToolManager.exit(0);
|
||||
} else {
|
||||
ToolManager.closeStage(primaryStage);
|
||||
}
|
||||
|
||||
});
|
||||
GuiUtils.tooltip(IMG_CLOSE, LRes.TIP_WINDOW_CLOSE);
|
||||
GuiUtils.setViewportChange(IMG_CLOSE, new GuiUtils.GetViewport() {
|
||||
@Override
|
||||
public Rectangle2D get(int index) {
|
||||
return new Rectangle2D(index*11,-1,11,13);
|
||||
}
|
||||
});
|
||||
}
|
||||
protected void setMinifyImage(ImageView IMG_MIN){
|
||||
IMG_MIN.setOnMouseClicked(event -> primaryStage.setIconified(true));
|
||||
GuiUtils.tooltip(IMG_MIN,LRes.TIP_WINDOW_MINIMIZE);
|
||||
GuiUtils.setViewportChange(IMG_MIN, new GuiUtils.GetViewport() {
|
||||
@Override
|
||||
public Rectangle2D get(int index) {
|
||||
return new Rectangle2D(index*11,-1,11,13);
|
||||
}
|
||||
});
|
||||
}
|
||||
@FXML
|
||||
protected abstract void initialize();
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
package com.xiaomitool.v2.gui.controller;
|
||||
|
||||
import com.xiaomitool.v2.gui.GuiObjects;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.engine.ToolManager;
|
||||
import com.xiaomitool.v2.gui.visual.LoadingAnimation;
|
||||
import com.xiaomitool.v2.gui.visual.TextScrollPane;
|
||||
import com.xiaomitool.v2.gui.visual.VisiblePane;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.Pointer;
|
||||
import com.xiaomitool.v2.utility.WaitSemaphore;
|
||||
import com.xiaomitool.v2.utility.utils.CookieUtils;
|
||||
import com.xiaomitool.v2.xiaomi.XiaomiKeystore;
|
||||
import javafx.application.Platform;
|
||||
import javafx.concurrent.Worker;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextAlignment;
|
||||
import javafx.scene.web.WebEngine;
|
||||
import javafx.scene.web.WebView;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.net.URI;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
public class LoginController extends DefaultController {
|
||||
private static final String LOGIN_URL = "https://account.xiaomi.com/pass/serviceLogin?sid=passport&json=false&passive=true&hidden=false&_snsDefault=facebook&_locale="+ Locale.getDefault().getLanguage().toLowerCase();
|
||||
|
||||
@FXML
|
||||
private HBox HEADER;
|
||||
@FXML
|
||||
private ImageView IMG_CLOSE;
|
||||
@FXML
|
||||
private WebView BROWSER;
|
||||
@FXML
|
||||
private Hyperlink WHY_LOGIN;
|
||||
@FXML
|
||||
private StackPane CONTENT;
|
||||
|
||||
private WebEngine ENGINE;
|
||||
private VisiblePane BROWSER_AREA;
|
||||
private Node LOADING_NODE = new LoadingAnimation.WithText(LRes.LOADING,70), CURRENT_NODE;
|
||||
private String passToken = null, userId=null, deviceId=null;
|
||||
private boolean isWhyLogin = false;
|
||||
private TextScrollPane WHY_LOGIN_TEXT = null;
|
||||
|
||||
|
||||
private boolean loadingLocalContent = false;
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
setCloseImage(IMG_CLOSE);
|
||||
initHeaderDrag(HEADER);
|
||||
initBrowser();
|
||||
initOnClick();
|
||||
initText();
|
||||
}
|
||||
|
||||
private void initText(){
|
||||
WHY_LOGIN.setText(LRes.LOGIN_WHY_LOGIN.toString());
|
||||
}
|
||||
|
||||
private void initOnClick(){
|
||||
WHY_LOGIN.setOnMouseClicked(event -> {
|
||||
if (isWhyLogin){
|
||||
BROWSER_AREA.add(CURRENT_NODE);
|
||||
WHY_LOGIN.setText(LRes.LOGIN_WHY_LOGIN.toString());
|
||||
} else {
|
||||
if (WHY_LOGIN_TEXT == null){
|
||||
Text loginText = new Text(LRes.LOGIN_WHY_LOGIN_TEXT.toString());
|
||||
loginText.setFont(Font.font(14));
|
||||
loginText.setTextAlignment(TextAlignment.CENTER);
|
||||
WHY_LOGIN_TEXT = new TextScrollPane(loginText);
|
||||
WHY_LOGIN_TEXT.setPadding(new Insets(30,60,30,60));
|
||||
}
|
||||
BROWSER_AREA.add(WHY_LOGIN_TEXT);
|
||||
WHY_LOGIN.setText(LRes.OK_UNDERSTAND.toString());
|
||||
}
|
||||
isWhyLogin = !isWhyLogin;
|
||||
});
|
||||
}
|
||||
|
||||
private void initBrowser(){
|
||||
BROWSER_AREA = new VisiblePane(CONTENT);
|
||||
BROWSER_AREA.add(LOADING_NODE);
|
||||
|
||||
ENGINE = BROWSER.getEngine();
|
||||
ENGINE.load(LOGIN_URL);
|
||||
Pointer pointer = new Pointer();
|
||||
pointer.pointed = new CookieUtils.EventCookieAdd() {
|
||||
@Override
|
||||
public boolean run(URI url, HttpCookie cookie) {
|
||||
Log.debug("New cookie: url: "+url.toString()+", cookie: "+cookie);
|
||||
String name = cookie.getName();
|
||||
if ("passToken".equals(name)){
|
||||
passToken = cookie.getValue();
|
||||
} else if ("deviceId".equals(name)){
|
||||
deviceId = cookie.getValue();
|
||||
} else if ("userId".equals(name)){
|
||||
userId = cookie.getValue();
|
||||
}
|
||||
if (passToken != null && userId != null && deviceId != null && !passToken.isEmpty() && !userId.isEmpty() && !deviceId.isEmpty()){
|
||||
loginDone();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
CookieUtils.addCookieListener((CookieUtils.EventCookieAdd) pointer.pointed);
|
||||
ENGINE.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
|
||||
Log.debug("New browser state: old: "+oldValue+", new: "+newValue);
|
||||
if (loadingLocalContent){
|
||||
return;
|
||||
}
|
||||
if (BROWSER_AREA == null){
|
||||
return;
|
||||
}
|
||||
if (Worker.State.RUNNING.equals(newValue)){
|
||||
setLoadingPage();
|
||||
} else if (Worker.State.FAILED.equals(newValue)){
|
||||
setErrorPage();
|
||||
} else if (Worker.State.SUCCEEDED.equals(newValue)){
|
||||
setBrowserPage();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loginDone(){
|
||||
Log.debug("Login done succesfully");
|
||||
XiaomiKeystore.getInstance().setCredentials(userId,passToken,deviceId);
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setLoginNumber(userId);
|
||||
ToolManager.closeStage(primaryStage);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void setLoadingPage(){
|
||||
CURRENT_NODE = LOADING_NODE;
|
||||
if (!isWhyLogin) {
|
||||
BROWSER_AREA.add(CURRENT_NODE);
|
||||
}
|
||||
}
|
||||
private void setErrorPage(){
|
||||
loadingLocalContent = true;
|
||||
ENGINE.loadContent("Connection error!");
|
||||
setBrowserPage();
|
||||
loadingLocalContent = false;
|
||||
|
||||
}
|
||||
private void setBrowserPage(){
|
||||
CURRENT_NODE = BROWSER;
|
||||
if (!isWhyLogin) {
|
||||
BROWSER_AREA.add(CURRENT_NODE);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean loggedIn = false;
|
||||
private static Thread loginThread = null;
|
||||
public static boolean isLogged(){
|
||||
return loggedIn;
|
||||
}
|
||||
public static void loginClick(){
|
||||
if (loggedIn){
|
||||
logout();
|
||||
} else {
|
||||
if (loginThread != null && loginThread.isAlive()){
|
||||
return;
|
||||
}
|
||||
Runnable runnable = loginRunnable();
|
||||
loginThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runnable.run();
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isLogged()){
|
||||
WindowManager.toast(LRes.LOGIN_SUCCESS.toString());
|
||||
} else {
|
||||
WindowManager.toast(LRes.LOGIN_CANCELED.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
loginThread.start();
|
||||
}
|
||||
}
|
||||
public static void logout(){
|
||||
CookieUtils.clear();
|
||||
XiaomiKeystore.clear();
|
||||
setLoginNumber(null);
|
||||
}
|
||||
|
||||
|
||||
public static Runnable loginRunnable() {
|
||||
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String userId = XiaomiKeystore.getInstance().getUserId();
|
||||
if (userId != null && !userId.isEmpty() ){
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setLoginNumber(userId);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
WaitSemaphore semaphore = new WaitSemaphore();
|
||||
Platform.runLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Stage stage = WindowManager.launchLogin();
|
||||
stage.setOnHidden(new EventHandler<WindowEvent>() {
|
||||
@Override
|
||||
public void handle(WindowEvent event) {
|
||||
semaphore.increase();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
try {
|
||||
semaphore.waitOnce();
|
||||
} catch (InterruptedException e) {
|
||||
Log.error("Login thread interrupted: "+e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
public static void setLoginNumber(String userId){
|
||||
if (userId == null){
|
||||
userId = "";
|
||||
}
|
||||
Label uidLabel = (Label) GuiObjects.getNode(GuiObjects.LOGIN_NUMBER);
|
||||
if (uidLabel == null){
|
||||
Log.error("Cannot set userId label: null object");
|
||||
return;
|
||||
}
|
||||
uidLabel.setText(userId);
|
||||
loggedIn = !userId.isEmpty();
|
||||
String text = loggedIn ? "Logout" : "Login";
|
||||
Log.debug("Setting loggedIn to: "+loggedIn);
|
||||
Hyperlink link = (Hyperlink) GuiObjects.getNode(GuiObjects.LOGIN_LINK);
|
||||
if (link == null){
|
||||
Log.error("Cannot set login hyperLink: null object");
|
||||
return;
|
||||
}
|
||||
link.setText(text);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.xiaomitool.v2.gui.controller;
|
||||
|
||||
import com.xiaomitool.v2.engine.ToolManager;
|
||||
import com.xiaomitool.v2.engine.ToolRunner;
|
||||
import com.xiaomitool.v2.gui.GuiObjects;
|
||||
import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
|
||||
import com.xiaomitool.v2.gui.visual.VisiblePane;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class MainWindowController extends DefaultController {
|
||||
private Stage primaryStage;
|
||||
private double stageX, stageY;
|
||||
@FXML
|
||||
private HBox HEADER;
|
||||
|
||||
@FXML
|
||||
private ImageView IMG_SETTINGS, IMG_CLOSE, IMG_MIN;
|
||||
|
||||
@FXML
|
||||
private Hyperlink TRANSLATED_LINK, LOGIN_LINK;
|
||||
@FXML
|
||||
private Label LOGIN_NUMBER, VERSION_NUMBER, TEXT_TRANSLATED_BY;
|
||||
@FXML
|
||||
private BorderPane BORDER_PANE;
|
||||
|
||||
public MainWindowController(){}
|
||||
public MainWindowController(Stage primaryStage){
|
||||
super(primaryStage);
|
||||
this.primaryStage = primaryStage;
|
||||
}
|
||||
|
||||
@FXML
|
||||
protected void initialize()
|
||||
{
|
||||
saveNodes();
|
||||
initHeaderDrag(HEADER);
|
||||
setSettingsImage(IMG_SETTINGS);
|
||||
setCloseImage(IMG_CLOSE, true);
|
||||
setMinifyImage(IMG_MIN);
|
||||
initOnClick();
|
||||
initVisiblePane();
|
||||
initDisclaimer();
|
||||
initText();
|
||||
|
||||
|
||||
}
|
||||
private void initText(){
|
||||
TEXT_TRANSLATED_BY.setText(LRes.TRANSLATED_BY.toString());
|
||||
String version ="V"+ToolManager.TOOL_VERSION;
|
||||
if (ToolManager.TOOL_VERSION_EX != null && !ToolManager.TOOL_VERSION_EX.isEmpty()){
|
||||
version+=" ("+ToolManager.TOOL_VERSION_EX+")";
|
||||
}
|
||||
VERSION_NUMBER.setText(version);
|
||||
}
|
||||
|
||||
private void initVisiblePane(){
|
||||
VisiblePane pane = new VisiblePane();
|
||||
WindowManager.setMainVisiblePane(pane);
|
||||
BORDER_PANE.setCenter(pane.getPane());
|
||||
}
|
||||
|
||||
private void initDisclaimer(){
|
||||
ToolRunner.start();
|
||||
|
||||
}
|
||||
|
||||
private void saveNodes(){
|
||||
GuiObjects.set(GuiObjects.IMG_CLOSE, IMG_CLOSE);
|
||||
GuiObjects.set(GuiObjects.IMG_MINIFY,IMG_MIN);
|
||||
GuiObjects.set(GuiObjects.IMG_SETTINGS,IMG_SETTINGS);
|
||||
GuiObjects.set(GuiObjects.LOGIN_LINK, LOGIN_LINK);
|
||||
GuiObjects.set(GuiObjects.LOGIN_NUMBER, LOGIN_NUMBER);
|
||||
}
|
||||
|
||||
private void setSettingsImage(ImageView IMG_SETTINGS){
|
||||
GuiUtils.setViewportChange(IMG_SETTINGS, new GuiUtils.GetViewport() {
|
||||
@Override
|
||||
public Rectangle2D get(int index) {
|
||||
return new Rectangle2D(5+index*24,0,14,14);
|
||||
}
|
||||
});
|
||||
GuiUtils.tooltip(IMG_SETTINGS, LRes.TIP_WINDOW_SETTINGS);
|
||||
IMG_SETTINGS.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent event) {
|
||||
WindowManager.launchSettings();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
private void initOnClick(){
|
||||
LOGIN_LINK.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent event) {
|
||||
LoginController.loginClick();
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.xiaomitool.v2.gui.controller;
|
||||
|
||||
import com.xiaomitool.v2.gui.PopupWindow;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.StackPane;
|
||||
|
||||
|
||||
public class PopupController extends DefaultController {
|
||||
@FXML
|
||||
Region HEADER_REGION;
|
||||
@FXML
|
||||
ImageView IMG_CLOSE;
|
||||
@FXML
|
||||
HBox HEADER;
|
||||
@FXML
|
||||
StackPane CONTENT_PANE;
|
||||
|
||||
private PopupWindow popupWindow;
|
||||
|
||||
public PopupController(PopupWindow popupWindow) {
|
||||
this.popupWindow = popupWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
initHeaderDrag(HEADER);
|
||||
setCloseImage(IMG_CLOSE);
|
||||
double w = popupWindow.getWidth()-150;
|
||||
if (w > 0){
|
||||
HEADER_REGION.setPrefWidth(w);
|
||||
}
|
||||
if (popupWindow.getContent() != null){
|
||||
CONTENT_PANE.getChildren().add(popupWindow.getContent());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package com.xiaomitool.v2.gui.controller;
|
||||
|
||||
import com.xiaomitool.v2.gui.WindowManager;
|
||||
import com.xiaomitool.v2.language.LRes;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.utils.SettingsUtils;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.stage.DirectoryChooser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class SettingsController extends DefaultController {
|
||||
@FXML
|
||||
private ImageView IMG_CLOSE;
|
||||
@FXML
|
||||
private HBox HEADER;
|
||||
@FXML
|
||||
private Label LABEL_DOWNLOAD, LABEL_EXTRACT, TEXT_DOWNLOAD, TEXT_EXTRACT;
|
||||
@FXML
|
||||
private Button BUTTON_DOWNLOAD, BUTTON_EXTRACT, BUTTON_CLEAR, BUTTON_RESET;
|
||||
@FXML
|
||||
private CheckBox CHECK_SAVE_LOGIN;
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
setCloseImage(IMG_CLOSE);
|
||||
initHeaderDrag(HEADER);
|
||||
initCss();
|
||||
initTexts();
|
||||
loadSettings();
|
||||
initOnClick();
|
||||
}
|
||||
|
||||
private void initCss(){
|
||||
TEXT_EXTRACT.setStyle("-fx-text-overrun: leading-ellipsis;");
|
||||
TEXT_DOWNLOAD.setStyle("-fx-text-overrun: leading-ellipsis;");
|
||||
BUTTON_CLEAR.setDisable(true);
|
||||
}
|
||||
private void initTexts(){
|
||||
LABEL_DOWNLOAD.setText(LRes.SETTINGS_DOWNLOAD_DIR.toString());
|
||||
LABEL_EXTRACT.setText(LRes.SETTINGS_EXTRACT_DIR.toString());
|
||||
BUTTON_DOWNLOAD.setText(LRes.CHOOSE.toString());
|
||||
BUTTON_CLEAR.setText(LRes.SETTINGS_CLEAR.toString());
|
||||
BUTTON_EXTRACT.setText(LRes.CHOOSE.toString());
|
||||
CHECK_SAVE_LOGIN.setText(LRes.SETTINGS_SAVE_SESSION.toString());
|
||||
}
|
||||
|
||||
private void loadSettings(){
|
||||
SettingsUtils.load();
|
||||
Path downloadDir = SettingsUtils.getDownloadPath();
|
||||
Path extractDir = SettingsUtils.getExtractPath();
|
||||
String ddir, edir;
|
||||
try {
|
||||
ddir = downloadDir.toFile().getCanonicalPath();
|
||||
edir = extractDir.toFile().getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
ddir = downloadDir.toString();
|
||||
edir = extractDir.toString();
|
||||
}
|
||||
TEXT_DOWNLOAD.setText(ddir);
|
||||
Log.debug(TEXT_DOWNLOAD.getLayoutBounds().getWidth());
|
||||
TEXT_EXTRACT.setText(edir);
|
||||
String saveSession = SettingsUtils.getOpt(SettingsUtils.PREF_SAVE_SESSION);
|
||||
boolean bool = "true".equalsIgnoreCase(saveSession);
|
||||
CHECK_SAVE_LOGIN.setSelected(bool);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void initOnClick(){
|
||||
BUTTON_EXTRACT.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent event) {
|
||||
DirectoryChooser directoryChooser = new DirectoryChooser();
|
||||
directoryChooser.setInitialDirectory(SettingsUtils.getExtractPath().toFile());
|
||||
File choice = directoryChooser.showDialog(WindowManager.mainWindow());
|
||||
if (choice == null){
|
||||
return;
|
||||
}
|
||||
String path;
|
||||
try {
|
||||
path = choice.getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
path = choice.getAbsolutePath();
|
||||
}
|
||||
SettingsUtils.saveOpt(SettingsUtils.PREF_EXTRACT_DIR, path);
|
||||
TEXT_EXTRACT.setText(path);
|
||||
}
|
||||
});
|
||||
BUTTON_DOWNLOAD.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent event) {
|
||||
DirectoryChooser directoryChooser = new DirectoryChooser();
|
||||
directoryChooser.setInitialDirectory(SettingsUtils.getDownloadPath().toFile());
|
||||
File choice = directoryChooser.showDialog(WindowManager.mainWindow());
|
||||
if (choice == null){
|
||||
return;
|
||||
}
|
||||
String path;
|
||||
try {
|
||||
path = choice.getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
path = choice.getAbsolutePath();
|
||||
}
|
||||
SettingsUtils.saveOpt(SettingsUtils.PREF_DOWNLOAD_DIR, path);
|
||||
TEXT_DOWNLOAD.setText(path);
|
||||
}
|
||||
});
|
||||
CHECK_SAVE_LOGIN.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent event) {
|
||||
String val = CHECK_SAVE_LOGIN.isSelected() ? "true" : "false";
|
||||
SettingsUtils.saveOpt(SettingsUtils.PREF_SAVE_SESSION,val);
|
||||
}
|
||||
});
|
||||
|
||||
BUTTON_RESET.setOnAction(new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent event) {
|
||||
SettingsUtils.unset(SettingsUtils.PREF_SAVE_SESSION);
|
||||
SettingsUtils.unset(SettingsUtils.PREF_DOWNLOAD_DIR);
|
||||
SettingsUtils.unset(SettingsUtils.PREF_EXTRACT_DIR);
|
||||
String dp, ep;
|
||||
|
||||
try {
|
||||
dp = SettingsUtils.getDownloadPath().toFile().getCanonicalPath();
|
||||
ep = SettingsUtils.getExtractPath().toFile().getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
dp = SettingsUtils.getDownloadPath().toString();
|
||||
ep = SettingsUtils.getExtractPath().toString();
|
||||
}
|
||||
TEXT_DOWNLOAD.setText(dp);
|
||||
TEXT_EXTRACT.setText(ep);
|
||||
CHECK_SAVE_LOGIN.setSelected(false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.xiaomitool.v2.gui.deviceView;
|
||||
|
||||
public interface Animatable {
|
||||
|
||||
public void animate(int times, long duration);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.xiaomitool.v2.gui.deviceView;
|
||||
|
||||
import javafx.scene.image.Image;
|
||||
|
||||
public class DeviceImage {
|
||||
|
||||
private Image deviceImage;
|
||||
private double topOffset, leftOffset, heightInner, widthInner, heightOuter, widthOuter;
|
||||
private DeviceView.ButtonPosition volumeUp, volumeDown, power;
|
||||
|
||||
public DeviceImage(Image image, double top, double left, double heightInner, double widthInner, double heightOuter, double widthOuter, DeviceView.ButtonPosition volumeUp, DeviceView.ButtonPosition volumeDown, DeviceView.ButtonPosition power) {
|
||||
this.deviceImage = image;
|
||||
this.topOffset = top;
|
||||
this.leftOffset = left;
|
||||
this.heightInner = heightInner;
|
||||
this.widthInner = widthInner;
|
||||
this.widthOuter = widthOuter;
|
||||
this.heightOuter = heightOuter;
|
||||
this.volumeDown = volumeDown;
|
||||
this.volumeUp = volumeUp;
|
||||
this.power = power;
|
||||
}
|
||||
|
||||
public double getLeftOffset() {
|
||||
return leftOffset;
|
||||
}
|
||||
|
||||
public double getTopOffset() {
|
||||
return topOffset;
|
||||
}
|
||||
|
||||
public Image getDeviceImage() {
|
||||
return deviceImage;
|
||||
}
|
||||
|
||||
public double getInnerHeight() {
|
||||
return heightInner;
|
||||
}
|
||||
|
||||
public double getInnerWidth() {
|
||||
return widthInner;
|
||||
}
|
||||
|
||||
public double getOuterWidth() {
|
||||
return widthOuter;
|
||||
}
|
||||
|
||||
public double getOuterHeight() {
|
||||
return heightOuter;
|
||||
}
|
||||
|
||||
public DeviceView.ButtonPosition getVolumeDown() {
|
||||
return volumeDown;
|
||||
}
|
||||
|
||||
public DeviceView.ButtonPosition getPower() {
|
||||
return power;
|
||||
}
|
||||
|
||||
public DeviceView.ButtonPosition getVolumeUp() {
|
||||
return volumeUp;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.xiaomitool.v2.gui.deviceView;
|
||||
|
||||
|
||||
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 javafx.scene.effect.BlendMode;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.paint.Color;
|
||||
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()));
|
||||
public DeviceRecoveryView(DeviceImage deviceImage, double wantedHeight) {
|
||||
super(deviceImage, wantedHeight, Color.BLACK, null);
|
||||
|
||||
this.setContent(recoveryImage);
|
||||
selectOption(1);
|
||||
//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.setFill(Color.rgb(51,180, 255));
|
||||
rectangle.setBlendMode(BlendMode.ADD);
|
||||
rectangle.setArcWidth(6);
|
||||
rectangle.setArcHeight(6);
|
||||
return rectangle;
|
||||
}
|
||||
public void selectOption(int index){
|
||||
if (selectRectangle == null){
|
||||
selectRectangle = buildSelectRectangle();
|
||||
Log.debug("Rectangle built");
|
||||
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
public void animateSelectThird(long duration){
|
||||
DeviceRecoveryView view = this;
|
||||
setContent(recoveryImage);
|
||||
this.selectOption(0);
|
||||
this.setClickVolumeDown(1).setOnFinished(event -> {
|
||||
selectOption(1);
|
||||
setClickVolumeDown(1).setOnFinished(event1 -> {
|
||||
selectOption(2);
|
||||
setClickPower(1).setOnFinished(event2 -> {
|
||||
setContent(pcsuiteImage, true);
|
||||
GuiUtils.waitGui(duration, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (GuiUtils.hasParent(view,WindowManager.getMainPane())){
|
||||
animateSelectThird(duration);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void animate(int times, long duration) {
|
||||
animateSelectThird(duration);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
package com.xiaomitool.v2.gui.deviceView;
|
||||
|
||||
import com.xiaomitool.v2.gui.GuiUtils;
|
||||
import com.xiaomitool.v2.gui.drawable.DrawableManager;
|
||||
import com.xiaomitool.v2.gui.visual.OverlayPane;
|
||||
import com.xiaomitool.v2.logging.Log;
|
||||
import com.xiaomitool.v2.utility.Nullable;
|
||||
import com.xiaomitool.v2.utility.Pointer;
|
||||
|
||||
import javafx.animation.*;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.effect.InnerShadow;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public class DeviceView extends StackPane {
|
||||
private DeviceImage deviceImage;
|
||||
private ImageView deviceBorders, displayedImageView;
|
||||
protected double wantedHeight, scaleRatio;
|
||||
private Color background = Color.rgb(49, 53, 57), innerShadow = Color.BLACK;
|
||||
private StackPane contentPane;
|
||||
private Image displayedImage;
|
||||
protected Pane containerPane, imageWrapPane;
|
||||
|
||||
public static final DeviceImage DEVICE_16_9 = new DeviceImage(new Image(DrawableManager.getPng("device16_9").toString()),220,35,1920,1080,2360, 1160, new DeviceView.ButtonPosition(410,1150,10,200),new DeviceView.ButtonPosition(610,1150,10,200),new DeviceView.ButtonPosition(880,1150,10,200));
|
||||
public static final DeviceImage DEVICE_18_9 = new DeviceImage(new Image(DrawableManager.getPng("device18_9").toString()),130,25,2160,1080,2420, 1140, new DeviceView.ButtonPosition(300,1130,10,200),new DeviceView.ButtonPosition(500,1130,10,200),new DeviceView.ButtonPosition(800,1130,10,200));
|
||||
|
||||
public static Pane crop(DeviceView deviceView, double height, double top){
|
||||
return GuiUtils.crop(deviceView,0,top,deviceView.getWantedHeight()/deviceView.getOuterAspectRatio(),height);
|
||||
}
|
||||
public static Pane crop(DeviceView deviceView, double height){
|
||||
return crop(deviceView,height,0);
|
||||
}
|
||||
|
||||
public DeviceView(DeviceImage deviceImage, double wantedHeight) {
|
||||
this(deviceImage, wantedHeight, null, null);
|
||||
}
|
||||
|
||||
public DeviceView(DeviceImage deviceImage, double wantedHeight, @Nullable Color backgroundColor, @Nullable Color innerShadowColor) {
|
||||
if (backgroundColor != null) {
|
||||
this.background = backgroundColor;
|
||||
}
|
||||
if (innerShadowColor != null) {
|
||||
this.innerShadow = innerShadowColor;
|
||||
}
|
||||
this.deviceImage = deviceImage;
|
||||
this.wantedHeight = wantedHeight;
|
||||
super.setPrefHeight(wantedHeight);
|
||||
build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public double getWantedHeight() {
|
||||
return wantedHeight;
|
||||
}
|
||||
|
||||
private void build() {
|
||||
deviceBorders = new ImageView(deviceImage.getDeviceImage());
|
||||
deviceBorders.setPreserveRatio(true);
|
||||
deviceBorders.setFitHeight(wantedHeight);
|
||||
scaleRatio = wantedHeight / deviceImage.getOuterHeight();
|
||||
|
||||
contentPane = new StackPane();
|
||||
contentPane.setBackground(GuiUtils.backgroundFromColor(background));
|
||||
contentPane.setPrefHeight((scaleRatio * deviceImage.getInnerHeight())+4);
|
||||
contentPane.setPrefWidth((scaleRatio * deviceImage.getInnerWidth())+4);
|
||||
// contentPane.setAlignment(Pos.CENTER);
|
||||
contentPane.setEffect(new InnerShadow(0.1 * deviceImage.getInnerWidth() * scaleRatio, innerShadow));
|
||||
contentPane.setLayoutX(deviceImage.getLeftOffset() * scaleRatio-2);
|
||||
contentPane.setLayoutY(deviceImage.getTopOffset() * scaleRatio-2);
|
||||
contentPane.setPadding(new Insets(2,0,0,2));
|
||||
Pane paddingPane = new Pane(contentPane);
|
||||
|
||||
|
||||
// paddingPane.setAlignment(Pos.TOP_LEFT);
|
||||
StackPane superStack = new StackPane(paddingPane, deviceBorders);
|
||||
containerPane = new Pane(superStack);
|
||||
containerPane.setPrefHeight(wantedHeight+4);
|
||||
super.getChildren().add(containerPane);
|
||||
|
||||
}
|
||||
public void setContent(ImageView image){
|
||||
setContent(image,false);
|
||||
}
|
||||
|
||||
public void setContent(Image image){
|
||||
setContent(new ImageView(image));
|
||||
}
|
||||
public void setContent(Image image, boolean keepratio){
|
||||
setContent(new ImageView(image), keepratio);
|
||||
}
|
||||
public void setContent(URL url){
|
||||
setContent(new Image(url.toString()));
|
||||
}
|
||||
public void setContent(URL url, boolean keepratio){
|
||||
setContent(new Image(url.toString(), keepratio));
|
||||
}
|
||||
public double getOuterAspectRatio(){
|
||||
return deviceImage.getOuterHeight()/deviceImage.getOuterWidth();
|
||||
}
|
||||
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()));
|
||||
}
|
||||
//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();
|
||||
} else {
|
||||
height = displayedImage.getHeight();
|
||||
width = displayedImage.getWidth();
|
||||
}
|
||||
double setHeight = height-offsetY;
|
||||
double setWidth = width-offsetX;
|
||||
double innerRatio = deviceImage.getInnerHeight()/deviceImage.getInnerWidth();
|
||||
double imgRatio = setHeight/setWidth;
|
||||
if (innerRatio < imgRatio){
|
||||
Log.debug("Image is taller than frame: height -> "+setHeight);
|
||||
double h = Double.min(setHeight, deviceImage.getInnerHeight()*scaleRatio);
|
||||
//h = keepRatio ? Double.min(h, displayedImage.getHeight()) : h;
|
||||
image.setFitHeight(h);
|
||||
} else {
|
||||
double w = 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);
|
||||
|
||||
}
|
||||
//image.setFitHeight(wantedHeight * deviceImage.getInnerHeight() / deviceImage.getOuterHeight());
|
||||
contentPane.getChildren().clear();
|
||||
|
||||
displayedImageView = image;
|
||||
|
||||
imageWrapPane = new Pane(image);
|
||||
contentPane.getChildren().add(GuiUtils.center(imageWrapPane));
|
||||
|
||||
}
|
||||
|
||||
public void setLenOverlay(OverlayPane pane, double size, double lensZoomRatio) {
|
||||
if (displayedImageView == null){
|
||||
return;
|
||||
}
|
||||
Pane len = new Pane();
|
||||
len.setPrefSize(size + 2, size + 2);
|
||||
len.setPickOnBounds(false);
|
||||
len.setLayoutX(-size);
|
||||
len.setLayoutY(-size);
|
||||
//len.setStyle("-fx-background-radius: "+size/2+";");
|
||||
len.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, null, new BorderWidths(1))));
|
||||
len.setVisible(false);
|
||||
ImageView imageView = new ImageView(displayedImage);
|
||||
imageView.setViewport(new Rectangle2D(0, 0, size, size));
|
||||
imageView.setPreserveRatio(true);
|
||||
imageView.setFitHeight(size);
|
||||
imageView.setFitWidth(size);
|
||||
imageView.setLayoutX(1);
|
||||
imageView.setLayoutY(1);
|
||||
len.getChildren().add(imageView);
|
||||
pane.getChildren().add(len);
|
||||
Pointer pointer = new Pointer();
|
||||
pointer.pointed = lensZoomRatio;
|
||||
displayedImageView.setOnMouseEntered(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent event) {
|
||||
len.setVisible(true);
|
||||
}
|
||||
});
|
||||
displayedImageView.setOnMouseExited(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent event) {
|
||||
len.setVisible(false);
|
||||
}
|
||||
});
|
||||
displayedImageView.setCursor(Cursor.CROSSHAIR);
|
||||
|
||||
displayedImageView.setOnMouseMoved(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent event) {
|
||||
double x = event.getSceneX() + 1, y = event.getSceneY() + 1;
|
||||
if (x + size + 2 > pane.getWidth()) {
|
||||
x = event.getSceneX() - size - 2;
|
||||
}
|
||||
if (y + size + 2 > pane.getHeight()) {
|
||||
y = event.getSceneY() - size - 2;
|
||||
}
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
len.setLayoutX(x);
|
||||
len.setLayoutY(y);
|
||||
double viewPortSize = (1 / ((double) pointer.pointed)) * size;
|
||||
imageView.setViewport(new Rectangle2D(Double.max(0, Double.min(event.getX() / scaleRatio - viewPortSize / 2, displayedImage.getWidth() - viewPortSize)), Double.max(0, Double.min(displayedImage.getHeight() - viewPortSize, event.getY() / scaleRatio - viewPortSize / 2)), viewPortSize, viewPortSize));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Transition setClickVolumeDown(int times) {
|
||||
ButtonPosition pos = deviceImage.getVolumeDown();
|
||||
return setClick(pos, times);
|
||||
}
|
||||
public Pane getImagePane(){
|
||||
return containerPane;
|
||||
}
|
||||
|
||||
public void setImageBackground(Background background){
|
||||
if (contentPane != null){
|
||||
contentPane.setBackground(background);
|
||||
}
|
||||
}
|
||||
|
||||
public Transition setClickVolumeUp(int times) {
|
||||
ButtonPosition pos = deviceImage.getVolumeUp();
|
||||
return setClick(pos, times);
|
||||
}
|
||||
|
||||
public Transition setClickPower(int times) {
|
||||
ButtonPosition pos = deviceImage.getPower();
|
||||
return setClick(pos, times);
|
||||
}
|
||||
|
||||
private Transition setClick(ButtonPosition pos, int times) {
|
||||
if (pos == null) {
|
||||
return null;
|
||||
}
|
||||
Rectangle rectangle = new Rectangle(pos.left * scaleRatio, pos.top * scaleRatio, pos.width * scaleRatio, pos.height * scaleRatio);
|
||||
double centerX = (pos.left + pos.width / 2) ;
|
||||
double centerY = (pos.top + pos.height / 2) ;
|
||||
rectangle.setFill(Color.RED);
|
||||
containerPane.getChildren().add(rectangle);
|
||||
Transition transition = buildCircleTransition(centerX,centerY,times,false);
|
||||
transition.statusProperty().addListener((observable, oldValue, newValue) -> {
|
||||
Log.debug(oldValue.toString()+" -> "+newValue.toString());
|
||||
if (Animation.Status.STOPPED.equals(newValue)){
|
||||
containerPane.getChildren().removeAll(rectangle);
|
||||
}
|
||||
});
|
||||
return transition;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public double getScaleRatio() {
|
||||
return scaleRatio;
|
||||
}
|
||||
|
||||
public Transition buildCircleTransition(double x, double y, int times){
|
||||
return buildCircleTransition(x,y,times,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);
|
||||
circle.setStroke(Color.RED);
|
||||
circle.setFill(Color.TRANSPARENT);
|
||||
circle.setVisible(false);
|
||||
circle.setOpacity(0);
|
||||
|
||||
Transition transition = getCircleTransition(circle, times);
|
||||
containerPane.getChildren().add(circle);
|
||||
transition.statusProperty().addListener(new ChangeListener<Animation.Status>() {
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends Animation.Status> observable, Animation.Status oldValue, Animation.Status newValue) {
|
||||
Log.debug(oldValue.toString()+" -> "+newValue.toString());
|
||||
if (Animation.Status.STOPPED.equals(newValue)){
|
||||
circle.setVisible(false);
|
||||
containerPane.getChildren().removeAll(circle);
|
||||
} else if (Animation.Status.RUNNING.equals(newValue)){
|
||||
circle.setVisible(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
transition.play();
|
||||
return transition;
|
||||
}
|
||||
|
||||
private Transition getCircleTransition(Circle circle, int times) {
|
||||
ScaleTransition transition = new ScaleTransition(Duration.millis(1500), circle);
|
||||
transition.setFromX(0);
|
||||
transition.setFromY(0);
|
||||
transition.setToX(1);
|
||||
transition.setToY(1);
|
||||
transition.setAutoReverse(false);
|
||||
transition.setCycleCount(times);
|
||||
FadeTransition fadeTransition = new FadeTransition(Duration.millis(1500), circle);
|
||||
fadeTransition.setFromValue(1);
|
||||
fadeTransition.setToValue(0);
|
||||
fadeTransition.setAutoReverse(false);
|
||||
fadeTransition.setCycleCount(times);
|
||||
fadeTransition.setInterpolator(new Interpolator() {
|
||||
@Override
|
||||
protected double curve(double t) {
|
||||
return t*t;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return new ParallelTransition(transition,fadeTransition);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class ButtonPosition {
|
||||
public double top, left, width, height;
|
||||
|
||||
public ButtonPosition(double top, double left, double width, double height) {
|
||||
this.top = top;
|
||||
this.left = left;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xiaomitool.v2.gui.drawable;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public class DrawableManager {
|
||||
public static String FASTBOOT_LOGO = "fastboot.png";
|
||||
public static String MIUI10 = "miui10.png";
|
||||
public static String NO_CONNECTION = "no_connection.png";
|
||||
public static String DEVICE_AUTH = "device_auth.png";
|
||||
public static String ERROR = "error.png";
|
||||
public static URL getResource(String name){
|
||||
return DrawableManager.class.getResource(name);
|
||||
}
|
||||
public static URL getPng(String name){
|
||||
if (!name.endsWith(".png")){
|
||||
name+=".png";
|
||||
}
|
||||
return getResource(name);
|
||||
}
|
||||
}
|
||||
|
Depois Largura: | Altura: | Tamanho: 4.3 KiB |
|
Depois Largura: | Altura: | Tamanho: 9.5 KiB |
|
Depois Largura: | Altura: | Tamanho: 684 B |
|
Depois Largura: | Altura: | Tamanho: 40 KiB |
|
Depois Largura: | Altura: | Tamanho: 40 KiB |
|
Depois Largura: | Altura: | Tamanho: 154 KiB |
|
Depois Largura: | Altura: | Tamanho: 29 KiB |