针对普通手机,最低版本支持到android 5.0
GVR修改
修改sDaydreamPhoneOverrideForTesting
修改libgvr.so
修改MutableEGLConfigChooser
修改scanlineRacer的swapmode
1.0.2
.text:000834F6 CMP R4, #0
.text:000834F8 ITE NE
.text:000834FA MOVNE R4, #4
.text:000834FC MOVEQ R4, #0
00 2C 14 BF 04 24 00 24
改为
00 2C 14 BF 04 24 04 24
只有dev-keys
1.0.3
.text:000834F6 CMP R4, #0
.text:000834F8 ITE NE
.text:000834FA MOVNE R4, #4
.text:000834FC MOVEQ R4, #0
有dev-keys和test-keys
1.1.0
.text:000834F6 CMP R4, #0
.text:000834F8 ITE NE
.text:000834FA MOVNE R4, #4
.text:000834FC MOVEQ R4, #0
00 2C 14 BF 04 24 00 24
有dev-keys和test-keys
2,3,4,6,7同上
8
.text:000A6CC2 CMP R3, #0
.text:000A6CC4 ITE EQ
.text:000A6CC6 MOVEQ R4, #0
.text:000A6CC8 MOVNE R4, #4
00 2B 0C BF 00 24 04 24
改为
00 2B 0C BF 04 24 04 24
1.libgvr.so修改, 改方法有兼容问题,使用上面的方法
FEATURE_VR_MODE_HIGH_PERFORMANCE
46 45 41 54 55 52 45 5F 56 52 5F 4D 4F 44 45 5F 48 49 47 48 5F 50 45
52 46 4F 52 4D 41 4E 43 45 0setSwapMode0
FEATURE_WIFI
46 45 41 54 55 52 45 5F 57 49 46 49 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
2.0 替换mySDK.smali, 替换libmy.so
2.1 GvrSurfaceView.smali修改
com/google/vr/ndk/base/GvrSurfaceView
.method public setSwapMode(I)V
.locals 2
.prologue
添加
invoke-static {}, Lcom/play/my/mySDK;->getSwapMode()I
move-result p1
2.2 com/play/my/unity/myVrActivity,onCreate函数 添加
invoke-virtual {p0}, Lcom/play/my/unity/myVrActivity;->getApplicationContext()Landroid/content/Context;
move-result-object v3
sput-object v3, Lcom/play/my/mySDK;->mContext:Landroid/content/Context;
2.3 com/play/my/unity/myVrActivity,onCreate函数
invoke-virtual {v3, v4}, Ljava/lang/reflect/Constructor;->newInstance([Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v4
check-cast v4, Lcom/unity3d/player/UnityPlayer;
iput-object v4, p0, Lcom/play/my/unity/myVrActivity;->mUnityPlayer:Lcom/unity3d/player/UnityPlayer;
后面添加
invoke-static {}, Lcom/play/my/mySDK;->hookUnityFun()V
3.在程序启动时运行,在
com/play/my/unity/myVrActivity,onCreate函数 添加
.line 121
invoke-static {}, Lcom/play/my/mySDK;->setsDaydreamPhoneOverrideForTesting()V
.line 122
invoke-static {}, Lcom/play/my/mySDK;->setsFingerprint()V
代码实现如下:
private static void setsDaydreamPhoneOverrideForTesting() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
Class cls = Class.forName("com.google.vr.ndk.base.DaydreamUtils");
Field f = cls.getDeclaredField("sDaydreamPhoneOverrideForTesting");
f.setAccessible(true);
f.set(null, true);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private static void setsFingerprint() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
Class cls = Class.forName("android.os.Build");
Field f = cls.getDeclaredField("FINGERPRINT");
f.setAccessible(true);
String fingerPrint = (String) f.get(null);
if (!TextUtils.isEmpty(fingerPrint)) {
if (!fingerPrint.endsWith("dev-keys")) {
String end = fingerPrint.substring(fingerPrint.length() - 8);
String newFingerPrint = fingerPrint.replace(end, "dev-keys");
f.set(null, newFingerPrint);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
4,封装egl hook接口,添加位置:com/google/vr/ndk/base/GvrLayout->init-> return-void 前,
invoke-static {}, Lcom/play/my/mySDK;->hookFun()V
com.unity3d.unitygvr.GoogleVR->resume() 添加 mySDK.enableShowTip(true);
smali :
const/4 v0, 0x1
invoke-static {v0}, Lcom/play/my/mySDK;->enableShowTip(Z)V
com.unity3d.unitygvr.GoogleVR->pause() 添加 mySDK.enableShowTip(false);
smali:
const/4 v0, 0x0
invoke-static {v0}, Lcom/play/my/mySDK;->enableShowTip(Z)V
代码并且实现如下:
typedef EGLImageKHR (*FP_eglCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
FP_eglCreateImageKHR pfun_eglCreateImageKHR = NULL;
EGLImageKHR myeglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
{
LOGE("myeglCreateImageKHR");
EGLint eglImgAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE };
EGLImageKHR img = pfun_eglCreateImageKHR(dpy, eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR, buffer, eglImgAttrs);
return img;
}
typedef EGLClientBuffer (*FP_eglCreateNativeClientBufferANDROID)(const EGLint *attrib_list);
FP_eglCreateNativeClientBufferANDROID pfun_eglCreateNativeClientBufferANDROID = NULL;
EGLClientBuffer myeglCreateNativeClientBufferANDROID (const EGLint *attrib_list)
{
LOGE("myeglCreateNativeClientBufferANDROID");
GLuint textureId;
glGenTextures ( 1, &textureId );
glBindTexture ( GL_TEXTURE_2D, textureId );
int width = attrib_list[1];
int height = attrib_list[3];
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
return (EGLClientBuffer)textureId;
}
//typedef void (*__eglMustCastToProperFunctionPointerType)(void);
EGLAPI __eglMustCastToProperFunctionPointerType (*old_eglGetProcAddress)(const char *procname) = NULL;
EGLAPI __eglMustCastToProperFunctionPointerType my_eglGetProcAddress(const char *procname)
{
LOGE("my_eglGetProcAddress");
__eglMustCastToProperFunctionPointerType pfun = old_eglGetProcAddress(procname);
if(strcmp(procname, "eglCreateImageKHR") == 0)
{
LOGE("my_eglGetProcAddress, eglCreateImageKHR");
pfun_eglCreateImageKHR = (FP_eglCreateImageKHR)pfun;
pfun = (__eglMustCastToProperFunctionPointerType)myeglCreateImageKHR;
}
if(strcmp(procname, "eglCreateNativeClientBufferANDROID") == 0 )
{
LOGE("my_eglGetProcAddress, eglCreateNativeClientBufferANDROID");
pfun_eglCreateNativeClientBufferANDROID = (FP_eglCreateNativeClientBufferANDROID)pfun;
pfun = (__eglMustCastToProperFunctionPointerType)myeglCreateNativeClientBufferANDROID;
}
return pfun;
}
5、
com/google/vr/cardboard/MutableEglConfigChooser类中
public EGLConfig chooseConfig(EGL10 var1, EGLDisplay var2) {
// int[] var3 = new int[]{12324, 8, 12323, 8, 12322, 8, 12321, 0, 12325, 0, 12326, 0, 12352, 64, 12339, 4100, 12344};
4100 修改为4
5.1 针对华为等手机闪退 修改
com/google/vr/cardboard/MutableEglConfigChooser类中
public EGLConfig chooseConfig(EGL10 var1, EGLDisplay var2) 函数中
EGLConfig[] configs = new EGLConfig[1];
if(!var1.eglChooseConfig(var2, var3, configs, 1, var4) && this.forceMutableBuffer) {
throw new IllegalArgumentException("eglChooseConfig failed");
} else {
添加 configs变量,同时修改addScanlineRacingView 函数中,
this.eglFactory.setUsePriorityContext(false);
6、
com/google/vr/cardboard/MutableEglConfigChooser类中
private static EGLConfig chooseConfig(EGL10 var0, EGLDisplay var1, EGLConfig[] var2, boolean var3) {
EGLConfig[] var4 = var2;
int var5 = var2.length;
for(int var6 = 0; var6 < var5; ++var6) {
EGLConfig var7 = var4[var6];
int var8 = findConfigAttrib(var0, var1, var7, 12325, 0);
int var9 = findConfigAttrib(var0, var1, var7, 12326, 0);
int var10 = findConfigAttrib(var0, var1, var7, 12324, 0);
int var11 = findConfigAttrib(var0, var1, var7, 12323, 0);
int var12 = findConfigAttrib(var0, var1, var7, 12322, 0);
int var13 = findConfigAttrib(var0, var1, var7, 12339, 0);
if(var10 == 8 && var11 == 8 && var12 == 8 && var8 == 0 && var9 == 0 && (!var3 || (var13 & 0x4) != 0)) {
return var7;
}
}
// 4094 ->4
// for(int var6 = 0; var6 < var5; ++var6)
// {
// EGLConfig var7 = var4[var6];
// return var7;
//
// }
return null;
}