diff --git a/mpmaster/src/main/cpp/CMakeLists.txt b/mpmaster/src/main/cpp/CMakeLists.txt index 8b6e427c..93ed4c59 100644 --- a/mpmaster/src/main/cpp/CMakeLists.txt +++ b/mpmaster/src/main/cpp/CMakeLists.txt @@ -1,26 +1,17 @@ - -# For more information about using CMake with Android Studio, read the -# documentation: https://d.android.com/studio/projects/add-native-code.html - -# Sets the minimum version of CMake required to build the native library. - cmake_minimum_required(VERSION 3.18.1) - -# Declares and names the project. -add_definitions(-DTERMINAL_CLIENT) -add_definitions(-DTERMINAL_CLIENT_MNTN) - project("mpmaster") -# Creates and names a library, sets it as either STATIC -# or SHARED, and provides the relative paths to its source code. -# You can define multiple libraries, and CMake builds them for you. -# Gradle automatically packages shared libraries with your APK. -include_directories(${TERM_CORE_ROOT}) +# 全局定义 +add_definitions(-DTERMINAL_CLIENT -DTERMINAL_CLIENT_MNTN) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bzip2) +# 包含头文件路径 +include_directories( + ${TERM_CORE_ROOT} + ${CMAKE_CURRENT_SOURCE_DIR}/bzip2 + ${CMAKE_CURRENT_SOURCE_DIR}/bspatch +) -# 添加 bzip2 源码 +# 编译bzip2静态库 add_library(bz2 STATIC bzip2/blocksort.c bzip2/huffman.c @@ -28,53 +19,21 @@ add_library(bz2 STATIC bzip2/randtable.c bzip2/compress.c bzip2/decompress.c - bzip2/bzlib.c) - -add_definitions(-DBSPATCH_EXECUTABLE) - -add_library(bspatch STATIC - bspatch/bspatch.c + bzip2/bzlib.c ) -# 链接时使用本地编译的 bz2 库 -target_link_libraries(bspatch - bz2 - log) - - - -add_library( # Sets the name of the library. - mpmaster - - # Sets the library as a shared library. - SHARED - - # Provides a relative path to your source file(s). - mpmaster.cpp - bspatch/bspatch.c +# 编译bspatch静态库(依赖bzip2) +add_definitions(-DBSPATCH_EXECUTABLE) +add_definitions(-DBSDIFF_EXECUTABLE) +add_library(bspatch STATIC bspatch/bspatch.c) +add_library(bsdiff STATIC bspatch/bsdiff.c) +target_link_libraries(bspatch bsdiff bz2 log) # 显式链接依赖库 + +# 编译主JNI库(依赖bspatch和bzip2) +add_library(mpmaster SHARED mpmaster.cpp) +target_link_libraries(mpmaster + bspatch # 关键:添加bspatch依赖 + bsdiff + bz2 # 关键:添加bzip2依赖 + ${log-lib} ) - -# Searches for a specified prebuilt library and stores the path as a -# variable. Because CMake includes system libraries in the search path by -# default, you only need to specify the name of the public NDK library -# you want to add. CMake verifies that the library exists before -# completing its build. - -find_library( # Sets the name of the path variable. - log-lib - - # Specifies the name of the NDK library that - # you want CMake to locate. - log ) - -# Specifies libraries CMake should link to your target library. You -# can link multiple libraries, such as libraries you define in this -# build script, prebuilt third-party libraries, or system libraries. - -target_link_libraries( # Specifies the target library. - mpmaster - - # Links the target library to the log library - # included in the NDK. - - ${log-lib} ) diff --git a/mpmaster/src/main/cpp/bspatch/bsdiff.c b/mpmaster/src/main/cpp/bspatch/bsdiff.c new file mode 100644 index 00000000..34ca5d38 --- /dev/null +++ b/mpmaster/src/main/cpp/bspatch/bsdiff.c @@ -0,0 +1,443 @@ +/*- + * Copyright 2003-2005 Colin Percival + * Copyright 2012 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bsdiff.h" + +#include +#include + +#define MIN(x,y) (((x)<(y)) ? (x) : (y)) + +static void split(int64_t *I,int64_t *V,int64_t start,int64_t len,int64_t h) +{ + int64_t i,j,k,x,tmp,jj,kk; + + if(len<16) { + for(k=start;kstart) split(I,V,start,jj-start,h); + + for(i=0;ikk) split(I,V,kk,start+len-kk,h); +} + +static void qsufsort(int64_t *I,int64_t *V,const uint8_t *old,int64_t oldsize) +{ + int64_t buckets[256]; + int64_t i,h,len; + + for(i=0;i<256;i++) buckets[i]=0; + for(i=0;i0;i--) buckets[i]=buckets[i-1]; + buckets[0]=0; + + for(i=0;iy) { + *pos=I[st]; + return x; + } else { + *pos=I[en]; + return y; + } + }; + + x=st+(en-st)/2; + if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) { + return search(I,old,oldsize,new,newsize,x,en,pos); + } else { + return search(I,old,oldsize,new,newsize,st,x,pos); + }; +} + +static void offtout(int64_t x,uint8_t *buf) +{ + int64_t y; + + if(x<0) y=-x; else y=x; + + buf[0]=y%256;y-=buf[0]; + y=y/256;buf[1]=y%256;y-=buf[1]; + y=y/256;buf[2]=y%256;y-=buf[2]; + y=y/256;buf[3]=y%256;y-=buf[3]; + y=y/256;buf[4]=y%256;y-=buf[4]; + y=y/256;buf[5]=y%256;y-=buf[5]; + y=y/256;buf[6]=y%256;y-=buf[6]; + y=y/256;buf[7]=y%256; + + if(x<0) buf[7]|=0x80; +} + +static int64_t writedata(struct bsdiff_stream* stream, const void* buffer, int64_t length) +{ + int64_t result = 0; + + while (length > 0) + { + const int smallsize = (int)MIN(length, INT_MAX); + const int writeresult = stream->write(stream, buffer, smallsize); + if (writeresult == -1) + { + return -1; + } + + result += writeresult; + length -= smallsize; + buffer = (uint8_t*)buffer + smallsize; + } + + return result; +} + +struct bsdiff_request +{ + const uint8_t* old; + int64_t oldsize; + const uint8_t* new; + int64_t newsize; + struct bsdiff_stream* stream; + int64_t *I; + uint8_t *buffer; +}; + +static int bsdiff_internal(const struct bsdiff_request req) +{ + int64_t *I,*V; + int64_t scan,pos,len; + int64_t lastscan,lastpos,lastoffset; + int64_t oldscore,scsc; + int64_t s,Sf,lenf,Sb,lenb; + int64_t overlap,Ss,lens; + int64_t i; + uint8_t *buffer; + uint8_t buf[8 * 3]; + + if((V=req.stream->malloc((req.oldsize+1)*sizeof(int64_t)))==NULL) return -1; + I = req.I; + + qsufsort(I,V,req.old,req.oldsize); + req.stream->free(V); + + buffer = req.buffer; + + /* Compute the differences, writing ctrl as we go */ + scan=0;len=0;pos=0; + lastscan=0;lastpos=0;lastoffset=0; + while(scanoldscore+8)) break; + + if((scan+lastoffsetSf*2-lenf) { Sf=s; lenf=i; }; + }; + + lenb=0; + if(scan=lastscan+i)&&(pos>=i);i++) { + if(req.old[pos-i]==req.new[scan-i]) s++; + if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; }; + }; + }; + + if(lastscan+lenf>scan-lenb) { + overlap=(lastscan+lenf)-(scan-lenb); + s=0;Ss=0;lens=0; + for(i=0;iSs) { Ss=s; lens=i+1; }; + }; + + lenf+=lens-overlap; + lenb-=lens; + }; + + offtout(lenf,buf); + offtout((scan-lenb)-(lastscan+lenf),buf+8); + offtout((pos-lenb)-(lastpos+lenf),buf+16); + + /* Write control data */ + if (writedata(req.stream, buf, sizeof(buf))) + return -1; + + /* Write diff data */ + for(i=0;imalloc((oldsize+1)*sizeof(int64_t)))==NULL) + return -1; + + if((req.buffer=stream->malloc(newsize+1))==NULL) + { + stream->free(req.I); + return -1; + } + + req.old = old; + req.oldsize = oldsize; + req.new = new; + req.newsize = newsize; + req.stream = stream; + + result = bsdiff_internal(req); + + stream->free(req.buffer); + stream->free(req.I); + + return result; +} + + +#include + +#include +#include +#include +#include +#include +#include + +static int bz2_write(struct bsdiff_stream* stream, const void* buffer, int size) +{ + int bz2err; + BZFILE* bz2; + + bz2 = (BZFILE*)stream->opaque; + BZ2_bzWrite(&bz2err, bz2, (void*)buffer, size); + if (bz2err != BZ_STREAM_END && bz2err != BZ_OK) + return -1; + + return 0; +} + +int bsdiff_main(int argc, const char **argv) +{ + int fd; + int bz2err; + uint8_t *old,*new; + off_t oldsize,newsize; + uint8_t buf[8]; + FILE * pf; + struct bsdiff_stream stream; + BZFILE* bz2; + + memset(&bz2, 0, sizeof(bz2)); + stream.malloc = malloc; + stream.free = free; + stream.write = bz2_write; + + if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); + + /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure + that we never try to malloc(0) and get a NULL pointer */ + if(((fd=open(argv[1],O_RDONLY,0))<0) || + ((oldsize=lseek(fd,0,SEEK_END))==-1) || + ((old=malloc(oldsize+1))==NULL) || + (lseek(fd,0,SEEK_SET)!=0) || + (read(fd,old,oldsize)!=oldsize) || + (close(fd)==-1)) err(1,"%s",argv[1]); + + + /* Allocate newsize+1 bytes instead of newsize bytes to ensure + that we never try to malloc(0) and get a NULL pointer */ + if(((fd=open(argv[2],O_RDONLY,0))<0) || + ((newsize=lseek(fd,0,SEEK_END))==-1) || + ((new=malloc(newsize+1))==NULL) || + (lseek(fd,0,SEEK_SET)!=0) || + (read(fd,new,newsize)!=newsize) || + (close(fd)==-1)) err(1,"%s",argv[2]); + + /* Create the patch file */ + if ((pf = fopen(argv[3], "w")) == NULL) + err(1, "%s", argv[3]); + + /* Write header (signature+newsize)*/ + offtout(newsize, buf); + if (fwrite("ENDSLEY/BSDIFF43", 16, 1, pf) != 1 || + fwrite(buf, sizeof(buf), 1, pf) != 1) + err(1, "Failed to write header"); + + + if (NULL == (bz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0))) + errx(1, "BZ2_bzWriteOpen, bz2err=%d", bz2err); + + stream.opaque = bz2; + if (bsdiff(old, oldsize, new, newsize, &stream)) + err(1, "bsdiff"); + + BZ2_bzWriteClose(&bz2err, bz2, 0, NULL, NULL); + if (bz2err != BZ_OK) + err(1, "BZ2_bzWriteClose, bz2err=%d", bz2err); + + if (fclose(pf)) + err(1, "fclose"); + + /* Free the memory we used */ + free(old); + free(new); + + return 0; +} + diff --git a/mpmaster/src/main/cpp/bspatch/bsdiff.h b/mpmaster/src/main/cpp/bspatch/bsdiff.h new file mode 100644 index 00000000..e30c2bff --- /dev/null +++ b/mpmaster/src/main/cpp/bspatch/bsdiff.h @@ -0,0 +1,44 @@ +/*- + * Copyright 2003-2005 Colin Percival + * Copyright 2012 Matthew Endsley + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted providing that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BSDIFF_H +# define BSDIFF_H + +# include +# include + +struct bsdiff_stream +{ + void* opaque; + + void* (*malloc)(size_t size); + void (*free)(void* ptr); + int (*write)(struct bsdiff_stream* stream, const void* buffer, int size); +}; + +int bsdiff(const uint8_t* old, int64_t oldsize, const uint8_t* new, int64_t newsize, struct bsdiff_stream* stream); +#endif diff --git a/mpmaster/src/main/cpp/bspatch/bspatch.c b/mpmaster/src/main/cpp/bspatch/bspatch.c index e35a8167..50e04339 100644 --- a/mpmaster/src/main/cpp/bspatch/bspatch.c +++ b/mpmaster/src/main/cpp/bspatch/bspatch.c @@ -27,6 +27,13 @@ #include #include "bspatch.h" +#ifdef __cplusplus +extern "C" { +#endif +int bspatch_main(int argc, char** argv); +#ifdef __cplusplus +} +#endif static int64_t offtin(uint8_t *buf) { diff --git a/mpmaster/src/main/cpp/bspatch/bspatch.h b/mpmaster/src/main/cpp/bspatch/bspatch.h index 099c36e4..e145111d 100644 --- a/mpmaster/src/main/cpp/bspatch/bspatch.h +++ b/mpmaster/src/main/cpp/bspatch/bspatch.h @@ -37,6 +37,5 @@ struct bspatch_stream }; int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream); - #endif diff --git a/mpmaster/src/main/cpp/mpmaster.cpp b/mpmaster/src/main/cpp/mpmaster.cpp index 8257e219..39522304 100644 --- a/mpmaster/src/main/cpp/mpmaster.cpp +++ b/mpmaster/src/main/cpp/mpmaster.cpp @@ -36,7 +36,25 @@ #define PATH_MPAPP_STATS "/sdcard/com.xypower.mpapp/data/stats/" #define PATH_MPAPP_RUNNING "/sdcard/com.xypower.mpapp/running" -extern int bspatch_main(int argc,char * argv[]); +//extern int bspatch_main(int argc,char * argv[]); +// 修正后的声明(添加到 mpmaster.cpp 顶部) +#ifdef __cplusplus +extern "C" { +#endif +int bspatch_main(int argc, char** argv); +//int bsdiff_main(int argc, char** argv); +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif +//int bspatch_main(int argc, char** argv); +int bsdiff_main(int argc, const char **argv); +#ifdef __cplusplus +} +#endif typedef struct { @@ -154,8 +172,7 @@ Java_com_xypower_mpmaster_MpMasterService_getSystemProperty( return env->NewStringUTF(value); } -extern "C" -JNIEXPORT jboolean JNICALL +extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpmaster_MpMasterService_applyPatch(JNIEnv *env, jclass clazz, jstring oldFile, jstring patchFile, jstring newFile) { const char *oldFilePath = env->GetStringUTFChars(oldFile, nullptr); @@ -169,7 +186,7 @@ Java_com_xypower_mpmaster_MpMasterService_applyPatch(JNIEnv *env, jclass clazz, const_cast("bspatch"), const_cast(oldFilePath), const_cast(newFilePath), - const_cast(patchFilePath) + const_cast(patchFilePath), }; int result = bspatch_main(4, argv); @@ -179,4 +196,24 @@ Java_com_xypower_mpmaster_MpMasterService_applyPatch(JNIEnv *env, jclass clazz, env->ReleaseStringUTFChars(patchFile, patchFilePath); return result == 0 ? JNI_TRUE : JNI_FALSE; -} \ No newline at end of file +} + +extern "C" JNIEXPORT jint JNICALL +Java_com_xypower_mpmaster_MpMasterService_applyDiff(JNIEnv *env, jclass clazz, jstring old_file, + jstring new_file, jstring patch_file) { + + // for cpp + const char *oldFile = env->GetStringUTFChars(old_file, 0); + const char *patchFile = env->GetStringUTFChars(patch_file, 0); + const char *newFile = env->GetStringUTFChars(new_file, 0); + + const char *argv[] = {"", oldFile, newFile, patchFile}; + + int result = bsdiff_main(4, argv); + + env->ReleaseStringUTFChars(old_file, oldFile); + env->ReleaseStringUTFChars(patch_file, patchFile); + env->ReleaseStringUTFChars(new_file, newFile); + + return result; +} diff --git a/mpmaster/src/main/java/com/xypower/mpmaster/MainActivity.java b/mpmaster/src/main/java/com/xypower/mpmaster/MainActivity.java index 94f42108..33513778 100644 --- a/mpmaster/src/main/java/com/xypower/mpmaster/MainActivity.java +++ b/mpmaster/src/main/java/com/xypower/mpmaster/MainActivity.java @@ -10,6 +10,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.os.StrictMode; import android.os.SystemClock; @@ -22,6 +23,7 @@ import android.widget.TextView; import com.dev.devapi.api.SysApi; import com.xypower.common.MicroPhotoContext; +import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; @@ -164,6 +166,32 @@ public class MainActivity extends AppCompatActivity { } }, 500); +// new Thread(new Runnable() { +// @Override +// public void run() { +// String path = Environment.getExternalStorageDirectory().getAbsolutePath(); +// if (!path.endsWith(File.separator)) { +// path += File.separator; +// } +// path += getApplicationContext().getPackageName() + File.separator; +// File pathFile = new File(path); +// if (!pathFile.exists() && !pathFile.mkdirs()) { +// } +// String old = pathFile.getAbsolutePath() + "/data/mpapp_v1.3.149_rel_20250429.apk"; +// String newapp = pathFile.getAbsolutePath() + "/data/mpapp_v1.3.150_rel_20250429.apk"; +// String patch = pathFile.getAbsolutePath() + "/data/test.patch"; +// String newpatch = pathFile.getAbsolutePath() + "/data/111.patch"; +// String newpath = pathFile.getAbsolutePath() + "/data/new.apk"; +// +// boolean b = MpMasterService.applyPatch(old, newpatch, newpath); +// System.out.println("" + b); +// +//// boolean b = MpMasterService.applyDiff(old, newapp, newpatch); +//// System.out.println("" + b); +// +// } +// }).start(); + } break; default: diff --git a/mpmaster/src/main/java/com/xypower/mpmaster/MpMasterService.java b/mpmaster/src/main/java/com/xypower/mpmaster/MpMasterService.java index 7f1aa858..8504f5cd 100644 --- a/mpmaster/src/main/java/com/xypower/mpmaster/MpMasterService.java +++ b/mpmaster/src/main/java/com/xypower/mpmaster/MpMasterService.java @@ -1515,6 +1515,7 @@ public class MpMasterService extends Service { public native static void rebootDevice(); public native static boolean applyPatch(String oldFile, String patchFile, String newFile); + public native static boolean applyDiff(String oldFile, String patchFile, String newFile); ////////////////////////GPS////////////////////