├── .gitattributes ├── .gitignore ├── .gitmodules ├── AndroidManifest.xml ├── README.md ├── build.xml ├── jni ├── Android.mk ├── Application.mk ├── dl_internal.h ├── dobby.cpp ├── dobby.h ├── dobby_public.h ├── main.cpp ├── main.h └── substrate.h ├── libs └── fmod.jar ├── prebuilts └── tinysubstrate-bin │ ├── Android.mk │ └── libgenericlauncher_tinysubstrate.so ├── proguard-project.txt ├── project.properties ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-ldpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── layout │ └── testbutton.xml └── values │ └── strings.xml └── src ├── .gitignore └── com ├── byteandahalf └── genericlauncher │ ├── GenericLauncher.java │ ├── NativeHandler.java │ ├── RedirectPackageManager.java │ ├── TestButton.java │ ├── Utils.java │ ├── WrappedPackageManager.java │ └── ui │ └── LauncherActivity.java └── mojang ├── android └── net │ ├── HTTPClientManager.java │ ├── HTTPRequest.java │ ├── HTTPResponse.java │ └── NoCertSSLSocketFactory.java └── minecraftpe ├── HardwareInformation.java ├── MainActivity.java └── store ├── NativeStoreListener.java ├── Product.java ├── Purchase.java ├── Store.java ├── StoreFactory.java └── StoreListener.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # vim swap file 6 | 7 | *.swp 8 | 9 | # files for the dex VM 10 | *.dex 11 | 12 | # Java class files 13 | *.class 14 | 15 | # generated files 16 | bin/ 17 | gen/ 18 | obj/ 19 | libs/armeabi-v7a/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Eclipse project files 25 | .classpath 26 | .project 27 | .settings/ 28 | 29 | # Proguard folder generated by Eclipse 30 | proguard/ 31 | 32 | # Intellij project files 33 | *.iml 34 | *.ipr 35 | *.iws 36 | .idea/ 37 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "jni/substrate"] 2 | path = jni/substrate 3 | url = git://git.saurik.com/substrate.git 4 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GenericLauncher 2 | ================ 3 | 4 | A base for Minecraft PE hacked clients. Starts you off with a basic launcher base that you can use to build off of. Currently just starts up and plays MCPE like normal, make it do what you want. 5 | 6 | Take the code, and do what you want with it. It's a base for anyone to use. Change the package name, don't give me cradit, I don't care. 7 | 8 | 9 | A few thanks to @zhuowei. This app is a barebones base of his app, BlockLauncher. -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 40 | 41 | 42 | 43 | 47 | 48 | 60 | 61 | 62 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | include $(CLEAR_VARS) 3 | LOCAL_LDLIBS := -llog 4 | LOCAL_MODULE := genericlauncher 5 | LOCAL_SRC_FILES := main.cpp dobby.cpp 6 | 7 | LOCAL_SHARED_LIBRARIES := tinysubstrate-bin 8 | 9 | include $(BUILD_SHARED_LIBRARY) 10 | 11 | $(call import-add-path, prebuilts) 12 | 13 | $(call import-module, tinysubstrate-bin) 14 | -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | 2 | APP_ABI := armeabi-v7a 3 | APP_PLATFORM := android-14 4 | APP_CFLAGS := -O2 -std=gnu99 -Wall 5 | APP_CPPFLAGS += -frtti -std=c++11 6 | 7 | APP_STL := gnustl_shared -------------------------------------------------------------------------------- /jni/dl_internal.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | typedef struct { 6 | char name[128]; 7 | const void* phdr; 8 | int phnum; 9 | unsigned entry; 10 | unsigned base; 11 | unsigned size; 12 | } soinfo2; 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /jni/dobby.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008, 2009 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | 32 | static Elf_Sym* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) { 33 | Elf_Sym* symtab = si->symtab; 34 | const char* strtab = si->strtab; 35 | 36 | for (unsigned n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]) { 37 | Elf_Sym* s = symtab + n; 38 | if (strcmp(strtab + s->st_name, name)) continue; 39 | 40 | /* only concern ourselves with global and weak symbol definitions */ 41 | switch (ELF_ST_BIND(s->st_info)) { 42 | case STB_GLOBAL: 43 | case STB_WEAK: 44 | if (s->st_shndx == SHN_UNDEF) { 45 | continue; 46 | } 47 | return s; 48 | } 49 | } 50 | 51 | return NULL; 52 | } 53 | 54 | static unsigned elfhash(const char* _name) { 55 | const unsigned char* name = (const unsigned char*) _name; 56 | unsigned h = 0, g; 57 | 58 | while(*name) { 59 | h = (h << 4) + *name++; 60 | g = h & 0xf0000000; 61 | h ^= g; 62 | h ^= g >> 24; 63 | } 64 | return h; 65 | } 66 | 67 | /* This is used by dlsym(3). It performs symbol lookup only within the 68 | specified soinfo object and not in any of its dependencies. 69 | 70 | TODO: Only looking in the specified soinfo seems wrong. dlsym(3) says 71 | that it should do a breadth first search through the dependency 72 | tree. This agrees with the ELF spec (aka System V Application 73 | Binary Interface) where in Chapter 5 it discuss resolving "Shared 74 | Object Dependencies" in breadth first search order. 75 | */ 76 | Elf_Sym* dlsym_handle_lookup(soinfo* si, const char* name) { 77 | return soinfo_elf_lookup(si, elfhash(name), name); 78 | } 79 | 80 | void* dobby_dlsym(void* handle, const char* symbol) { 81 | 82 | soinfo* found = NULL; 83 | Elf_Sym* sym = NULL; 84 | found = reinterpret_cast(handle); 85 | sym = dlsym_handle_lookup(found, symbol); 86 | 87 | if (sym != NULL) { 88 | return reinterpret_cast(sym->st_value + found->base/*load_bias*/); 89 | } 90 | __android_log_print(ANDROID_LOG_ERROR, "Dobby", "Failed when looking up %s\n", symbol); 91 | return NULL; 92 | } 93 | -------------------------------------------------------------------------------- /jni/dobby.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in 12 | * the documentation and/or other materials provided with the 13 | * distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _LINKER_H_ 30 | #define _LINKER_H_ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | 39 | #include "dobby_public.h" 40 | 41 | // Returns the address of the page containing address 'x'. 42 | #define PAGE_START(x) ((x) & PAGE_MASK) 43 | 44 | // Returns the offset of address 'x' in its page. 45 | #define PAGE_OFFSET(x) ((x) & ~PAGE_MASK) 46 | 47 | // Returns the address of the next page after address 'x', unless 'x' is 48 | // itself at the start of a page. 49 | #define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1)) 50 | 51 | // Magic shared structures that GDB knows about. 52 | 53 | struct link_map_t { 54 | uintptr_t l_addr; 55 | char* l_name; 56 | uintptr_t l_ld; 57 | link_map_t* l_next; 58 | link_map_t* l_prev; 59 | }; 60 | 61 | // Values for r_debug->state 62 | enum { 63 | RT_CONSISTENT, 64 | RT_ADD, 65 | RT_DELETE 66 | }; 67 | 68 | struct r_debug { 69 | int32_t r_version; 70 | link_map_t* r_map; 71 | void (*r_brk)(void); 72 | int32_t r_state; 73 | uintptr_t r_ldbase; 74 | }; 75 | 76 | #define FLAG_LINKED 0x00000001 77 | #define FLAG_EXE 0x00000004 // The main executable 78 | #define FLAG_LINKER 0x00000010 // The linker itself 79 | 80 | #define SOINFO_NAME_LEN 128 81 | 82 | typedef void (*linker_function_t)(); 83 | 84 | // Android uses REL for 32-bit but only uses RELA for 64-bit. 85 | #if defined(__LP64__) 86 | #define USE_RELA 1 87 | #endif 88 | 89 | struct soinfo { 90 | public: 91 | char name[SOINFO_NAME_LEN]; 92 | const Elf_Phdr* phdr; 93 | size_t phnum; 94 | Elf_Addr entry; 95 | Elf_Addr base; 96 | unsigned size; 97 | 98 | #ifndef __LP64__ 99 | uint32_t unused1; // DO NOT USE, maintained for compatibility. 100 | #endif 101 | 102 | Elf_Dyn* dynamic; 103 | 104 | #ifndef __LP64__ 105 | uint32_t unused2; // DO NOT USE, maintained for compatibility 106 | uint32_t unused3; // DO NOT USE, maintained for compatibility 107 | #endif 108 | 109 | soinfo* next; 110 | unsigned flags; 111 | 112 | const char* strtab; 113 | Elf_Sym* symtab; 114 | 115 | size_t nbucket; 116 | size_t nchain; 117 | unsigned* bucket; 118 | unsigned* chain; 119 | 120 | #if !defined(__LP64__) 121 | // This is only used by 32-bit MIPS, but needs to be here for 122 | // all 32-bit architectures to preserve binary compatibility. 123 | unsigned* plt_got; 124 | #endif 125 | 126 | #if defined(USE_RELA) 127 | Elf_Rela* plt_rela; 128 | size_t plt_rela_count; 129 | 130 | Elf_Rela* rela; 131 | size_t rela_count; 132 | #else 133 | Elf_Rel* plt_rel; 134 | size_t plt_rel_count; 135 | 136 | Elf_Rel* rel; 137 | size_t rel_count; 138 | #endif 139 | 140 | linker_function_t* preinit_array; 141 | size_t preinit_array_count; 142 | 143 | linker_function_t* init_array; 144 | size_t init_array_count; 145 | linker_function_t* fini_array; 146 | size_t fini_array_count; 147 | 148 | linker_function_t init_func; 149 | linker_function_t fini_func; 150 | 151 | #if defined(__arm__) 152 | // ARM EABI section used for stack unwinding. 153 | unsigned* ARM_exidx; 154 | size_t ARM_exidx_count; 155 | #elif defined(__mips__) 156 | unsigned mips_symtabno; 157 | unsigned mips_local_gotno; 158 | unsigned mips_gotsym; 159 | #endif 160 | 161 | size_t ref_count; 162 | link_map_t link_map; 163 | 164 | bool constructors_called; 165 | 166 | // When you read a virtual address from the ELF file, add this 167 | // value to get the corresponding address in the process' address space. 168 | Elf_Addr load_bias; 169 | 170 | #if !defined(__LP64__) 171 | bool has_text_relocations; 172 | #endif 173 | bool has_DT_SYMBOLIC; 174 | 175 | void CallConstructors(); 176 | void CallDestructors(); 177 | void CallPreInitConstructors(); 178 | 179 | private: 180 | void CallArray(const char* array_name, linker_function_t* functions, size_t count, bool reverse); 181 | void CallFunction(const char* function_name, linker_function_t function); 182 | }; 183 | 184 | extern soinfo libdl_info; 185 | 186 | void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path); 187 | soinfo* do_dlopen(const char* name, int flags); 188 | int do_dlclose(soinfo* si); 189 | 190 | Elf_Sym* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start); 191 | soinfo* find_containing_library(const void* addr); 192 | 193 | Elf_Sym* dladdr_find_symbol(soinfo* si, const void* addr); 194 | Elf_Sym* dlsym_handle_lookup(soinfo* si, const char* name); 195 | 196 | void debuggerd_init(); 197 | extern "C" void notify_gdb_of_libraries(); 198 | 199 | char* linker_get_error_buffer(); 200 | size_t linker_get_error_buffer_size(); 201 | 202 | #endif 203 | -------------------------------------------------------------------------------- /jni/dobby_public.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | void* dobby_dlsym(void* handle, const char* symbol); 5 | #ifdef __cplusplus 6 | } 7 | #endif 8 | -------------------------------------------------------------------------------- /jni/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | /* 18 | Put some typedefs and structs here 19 | */ 20 | typedef void Level; 21 | typedef void Player; 22 | typedef void Minecraft; 23 | typedef void MinecraftClient; 24 | typedef Player LocalPlayer; 25 | 26 | bool HEY_FUNCTIONS_HOOKED_ALREADY_BRO = false; 27 | 28 | JavaVM* javaVM; 29 | jclass nativehandler_class; 30 | 31 | static std::string (*hk_Common_getGameVersionString_real)(); 32 | static void (*hk_MinecraftClient_init_real)(MinecraftClient*); 33 | static bool (*hk_Minecraft_isModded_real)(Minecraft*); 34 | 35 | void MSHookFunction(void* symbol, void* hook, void** real); 36 | 37 | static Minecraft* minecraft_inst; 38 | static MinecraftClient* mcclient_inst; 39 | static LocalPlayer* localplayer_inst; 40 | static Level* level_inst = NULL; 41 | 42 | std::string hk_Common_getGameVersionString_hook() { 43 | // If the world hasn't loaded yet, print the usual version number(for the title screen) 44 | // else, return a blank string so the version watermark is absent in game. 45 | if (level_inst == NULL) { // Since I deleted the hook that gave Level a definition, Level will be always null 46 | return "v0.14.0"; 47 | } else { 48 | return " "; 49 | } 50 | } 51 | 52 | void hk_MinecraftClient_init_hook(MinecraftClient* client) { 53 | __android_log_print(ANDROID_LOG_INFO, "GenericLauncher", "MinecraftClient::init"); 54 | mcclient_inst = client; 55 | hk_MinecraftClient_init_real(client); 56 | } 57 | 58 | bool hk_Minecraft_isModded_hook(Minecraft* mc) { 59 | return true; 60 | } 61 | 62 | JNIEXPORT jint JNICALL Java_net_zhuoweizhang_pokerface_PokerFace_mprotect(JNIEnv* env, jclass clazz, jlong addr, jlong len, jint prot) { 63 | return mprotect((void *)(uintptr_t) addr, len, prot); 64 | } 65 | 66 | JNIEXPORT jlong JNICALL Java_net_zhuoweizhang_pokerface_PokerFace_sysconf(JNIEnv* env, jclass clazz, jint name) { 67 | long result = sysconf(name); 68 | return result; 69 | } 70 | 71 | JNIEXPORT void JNICALL Java_com_byteandahalf_genericlauncher_NativeHandler_nativeSetupHooks(JNIEnv* env, jclass clazz) { 72 | __android_log_print(ANDROID_LOG_INFO, "GenericLauncher", "SetupHook"); 73 | // Let's not call every hook 3.000.000 times, OK? 74 | if(HEY_FUNCTIONS_HOOKED_ALREADY_BRO == true) return; 75 | 76 | void *handle; 77 | handle = dlopen("libminecraftpe.so", RTLD_LAZY); 78 | soinfo2* weakhandle = (soinfo2*) dlopen("libminecraftpe.so", RTLD_LAZY); 79 | 80 | void* hk_Common_getGameVersionString = dlsym(handle, "_ZN6Common20getGameVersionStringEv"); 81 | MSHookFunction(hk_Common_getGameVersionString, (void*) &hk_Common_getGameVersionString_hook, (void**) &hk_Common_getGameVersionString_real); 82 | 83 | void* hk_MinecraftClient_init = dlsym(handle, "_ZN15MinecraftClient4initEv"); 84 | MSHookFunction(hk_MinecraftClient_init, (void*) &hk_MinecraftClient_init_hook, (void**) &hk_MinecraftClient_init_real); 85 | 86 | void* hk_Minecraft_isModded = dlsym(handle, "_ZN9Minecraft8isModdedEv"); 87 | MSHookFunction(hk_Minecraft_isModded, (void*) &hk_Minecraft_isModded_hook, (void**) &hk_Minecraft_isModded_real); 88 | 89 | dlerror(); 90 | 91 | jclass clz = env->FindClass("com/byteandahalf/genericlauncher/NativeHandler"); 92 | nativehandler_class = (jclass) env->NewGlobalRef(clz); // No idea why I have to cast to a jclass 93 | 94 | HEY_FUNCTIONS_HOOKED_ALREADY_BRO = true; 95 | 96 | const char* myerror = dlerror(); 97 | if (myerror != NULL) { 98 | __android_log_print(ANDROID_LOG_ERROR, "HALP", "Hooking errors: %s\n", myerror); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /jni/main.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class com_byteandahalf_genericlauncher_NativeHandler */ 4 | 5 | #ifndef _Included_com_byteandahalf_genericlauncher_NativeHandler 6 | #define _Included_com_byteandahalf_genericlauncher_NativeHandler 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | /* 11 | * Class: com_byteandahalf_genericlauncher_NativeHandler 12 | * Method: nativeSetupHooks 13 | * Signature: ()V 14 | */ 15 | JNIEXPORT void JNICALL Java_com_byteandahalf_genericlauncher_NativeHandler_nativeSetupHooks 16 | (JNIEnv *, jclass); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | #endif 22 | -------------------------------------------------------------------------------- /jni/substrate.h: -------------------------------------------------------------------------------- 1 | /* Cydia Substrate - Powerful Code Insertion Platform 2 | * Copyright (C) 2008-2011 Jay Freeman (saurik) 3 | */ 4 | 5 | /* GNU Lesser General Public License, Version 3 {{{ */ 6 | /* 7 | * Substrate is free software: you can redistribute it and/or modify it under 8 | * the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation, either version 3 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * Substrate is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 | * License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Substrate. If not, see . 19 | **/ 20 | /* }}} */ 21 | 22 | #ifndef SUBSTRATE_H_ 23 | #define SUBSTRATE_H_ 24 | 25 | #ifdef __APPLE__ 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | #include 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #include 35 | #include 36 | #endif 37 | 38 | #include 39 | #include 40 | 41 | #define _finline \ 42 | inline __attribute__((__always_inline__)) 43 | #define _disused \ 44 | __attribute__((__unused__)) 45 | 46 | #define _extern \ 47 | extern "C" __attribute__((__visibility__("default"))) 48 | 49 | #ifdef __cplusplus 50 | #define _default(value) = value 51 | #else 52 | #define _default(value) 53 | #endif 54 | 55 | #ifdef __cplusplus 56 | extern "C" { 57 | #endif 58 | 59 | bool MSHookProcess(pid_t pid, const char *library); 60 | 61 | typedef const void *MSImageRef; 62 | 63 | MSImageRef MSGetImageByName(const char *file); 64 | void *MSFindSymbol(MSImageRef image, const char *name); 65 | 66 | void MSHookFunction(void *symbol, void *replace, void **result); 67 | 68 | #ifdef __APPLE__ 69 | #ifdef __arm__ 70 | __attribute__((__deprecated__)) 71 | IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix _default(NULL)); 72 | #endif 73 | void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result); 74 | #endif 75 | 76 | #ifdef SubstrateInternal 77 | typedef void *SubstrateAllocatorRef; 78 | typedef struct __SubstrateProcess *SubstrateProcessRef; 79 | typedef struct __SubstrateMemory *SubstrateMemoryRef; 80 | 81 | SubstrateProcessRef SubstrateProcessCreate(SubstrateAllocatorRef allocator, pid_t pid); 82 | void SubstrateProcessRelease(SubstrateProcessRef process); 83 | 84 | SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size); 85 | void SubstrateMemoryRelease(SubstrateMemoryRef memory); 86 | #endif 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #ifdef __cplusplus 93 | 94 | #ifdef SubstrateInternal 95 | struct SubstrateHookMemory { 96 | SubstrateMemoryRef handle_; 97 | 98 | SubstrateHookMemory(SubstrateProcessRef process, void *data, size_t size) : 99 | handle_(SubstrateMemoryCreate(NULL, NULL, data, size)) 100 | { 101 | } 102 | 103 | ~SubstrateHookMemory() { 104 | if (handle_ != NULL) 105 | SubstrateMemoryRelease(handle_); 106 | } 107 | }; 108 | #endif 109 | 110 | #ifdef __APPLE__ 111 | 112 | namespace etl { 113 | 114 | template 115 | struct Case { 116 | static char value[Case_ + 1]; 117 | }; 118 | 119 | typedef Case Yes; 120 | typedef Case No; 121 | 122 | namespace be { 123 | template 124 | static Yes CheckClass_(void (Checked_::*)()); 125 | 126 | template 127 | static No CheckClass_(...); 128 | } 129 | 130 | template 131 | struct IsClass { 132 | void gcc32(); 133 | 134 | static const bool value = (sizeof(be::CheckClass_(0).value) == sizeof(Yes::value)); 135 | }; 136 | 137 | } 138 | 139 | #ifdef __arm__ 140 | template 141 | __attribute__((__deprecated__)) 142 | static inline Type_ *MSHookMessage(Class _class, SEL sel, Type_ *imp, const char *prefix = NULL) { 143 | return reinterpret_cast(MSHookMessage(_class, sel, reinterpret_cast(imp), prefix)); 144 | } 145 | #endif 146 | 147 | template 148 | static inline void MSHookMessage(Class _class, SEL sel, Type_ *imp, Type_ **result) { 149 | return MSHookMessageEx(_class, sel, reinterpret_cast(imp), reinterpret_cast(result)); 150 | } 151 | 152 | template 153 | static inline Type_ &MSHookIvar(id self, const char *name) { 154 | Ivar ivar(class_getInstanceVariable(object_getClass(self), name)); 155 | void *pointer(ivar == NULL ? NULL : reinterpret_cast(self) + ivar_getOffset(ivar)); 156 | return *reinterpret_cast(pointer); 157 | } 158 | 159 | #define MSAddMessage0(_class, type, arg0) \ 160 | class_addMethod($ ## _class, @selector(arg0), (IMP) &$ ## _class ## $ ## arg0, type); 161 | #define MSAddMessage1(_class, type, arg0) \ 162 | class_addMethod($ ## _class, @selector(arg0:), (IMP) &$ ## _class ## $ ## arg0 ## $, type); 163 | #define MSAddMessage2(_class, type, arg0, arg1) \ 164 | class_addMethod($ ## _class, @selector(arg0:arg1:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $, type); 165 | #define MSAddMessage3(_class, type, arg0, arg1, arg2) \ 166 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $, type); 167 | #define MSAddMessage4(_class, type, arg0, arg1, arg2, arg3) \ 168 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $, type); 169 | #define MSAddMessage5(_class, type, arg0, arg1, arg2, arg3, arg4) \ 170 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $, type); 171 | #define MSAddMessage6(_class, type, arg0, arg1, arg2, arg3, arg4, arg5) \ 172 | class_addMethod($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:), (IMP) &$ ## _class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $, type); 173 | 174 | #define MSHookMessage0(_class, arg0) \ 175 | MSHookMessage($ ## _class, @selector(arg0), MSHake(_class ## $ ## arg0)) 176 | #define MSHookMessage1(_class, arg0) \ 177 | MSHookMessage($ ## _class, @selector(arg0:), MSHake(_class ## $ ## arg0 ## $)) 178 | #define MSHookMessage2(_class, arg0, arg1) \ 179 | MSHookMessage($ ## _class, @selector(arg0:arg1:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $)) 180 | #define MSHookMessage3(_class, arg0, arg1, arg2) \ 181 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $)) 182 | #define MSHookMessage4(_class, arg0, arg1, arg2, arg3) \ 183 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $)) 184 | #define MSHookMessage5(_class, arg0, arg1, arg2, arg3, arg4) \ 185 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $)) 186 | #define MSHookMessage6(_class, arg0, arg1, arg2, arg3, arg4, arg5) \ 187 | MSHookMessage($ ## _class, @selector(arg0:arg1:arg2:arg3:arg4:arg5:), MSHake(_class ## $ ## arg0 ## $ ## arg1 ## $ ## arg2 ## $ ## arg3 ## $ ## arg4 ## $ ## arg5 ## $)) 188 | 189 | #define MSRegister_(name, dollar, colon) \ 190 | static class C_$ ## name ## $ ## dollar { public: _finline C_$ ## name ## $ ##dollar() { \ 191 | MSHookMessage($ ## name, @selector(colon), MSHake(name ## $ ## dollar)); \ 192 | } } V_$ ## name ## $ ## dollar; \ 193 | 194 | #define MSIgnore_(name, dollar, colon) 195 | 196 | #define MSMessage_(extra, type, _class, name, dollar, colon, call, args...) \ 197 | static type _$ ## name ## $ ## dollar(Class _cls, type (*_old)(_class, SEL, ## args, ...), type (*_spr)(struct objc_super *, SEL, ## args, ...), _class self, SEL _cmd, ## args); \ 198 | MSHook(type, name ## $ ## dollar, _class self, SEL _cmd, ## args) { \ 199 | Class const _cls($ ## name); \ 200 | type (* const _old)(_class, SEL, ## args, ...) = reinterpret_cast(_ ## name ## $ ## dollar); \ 201 | typedef type (*msgSendSuper_t)(struct objc_super *, SEL, ## args, ...); \ 202 | msgSendSuper_t const _spr(::etl::IsClass::value ? reinterpret_cast(&objc_msgSendSuper_stret) : reinterpret_cast(&objc_msgSendSuper)); \ 203 | return _$ ## name ## $ ## dollar call; \ 204 | } \ 205 | extra(name, dollar, colon) \ 206 | static _finline type _$ ## name ## $ ## dollar(Class _cls, type (*_old)(_class, SEL, ## args, ...), type (*_spr)(struct objc_super *, SEL, ## args, ...), _class self, SEL _cmd, ## args) 207 | 208 | /* for((x=1;x!=7;++x)){ echo -n "#define MSMessage${x}_(extra, type, _class, name";for((y=0;y!=x;++y));do echo -n ", sel$y";done;for((y=0;y!=x;++y));do echo -n ", type$y, arg$y";done;echo ") \\";echo -n " MSMessage_(extra, type, _class, name,";for((y=0;y!=x;++y));do if [[ $y -ne 0 ]];then echo -n " ##";fi;echo -n " sel$y ## $";done;echo -n ", ";for((y=0;y!=x;++y));do echo -n "sel$y:";done;echo -n ", (_cls, _old, _spr, self, _cmd";for((y=0;y!=x;++y));do echo -n ", arg$y";done;echo -n ")";for((y=0;y!=x;++y));do echo -n ", type$y arg$y";done;echo ")";} */ 209 | 210 | #define MSMessage0_(extra, type, _class, name, sel0) \ 211 | MSMessage_(extra, type, _class, name, sel0, sel0, (_cls, _old, _spr, self, _cmd)) 212 | #define MSMessage1_(extra, type, _class, name, sel0, type0, arg0) \ 213 | MSMessage_(extra, type, _class, name, sel0 ## $, sel0:, (_cls, _old, _spr, self, _cmd, arg0), type0 arg0) 214 | #define MSMessage2_(extra, type, _class, name, sel0, sel1, type0, arg0, type1, arg1) \ 215 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $, sel0:sel1:, (_cls, _old, _spr, self, _cmd, arg0, arg1), type0 arg0, type1 arg1) 216 | #define MSMessage3_(extra, type, _class, name, sel0, sel1, sel2, type0, arg0, type1, arg1, type2, arg2) \ 217 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $, sel0:sel1:sel2:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2), type0 arg0, type1 arg1, type2 arg2) 218 | #define MSMessage4_(extra, type, _class, name, sel0, sel1, sel2, sel3, type0, arg0, type1, arg1, type2, arg2, type3, arg3) \ 219 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $, sel0:sel1:sel2:sel3:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3), type0 arg0, type1 arg1, type2 arg2, type3 arg3) 220 | #define MSMessage5_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \ 221 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $ ## sel4 ## $, sel0:sel1:sel2:sel3:sel4:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3, arg4), type0 arg0, type1 arg1, type2 arg2, type3 arg3, type4 arg4) 222 | #define MSMessage6_(extra, type, _class, name, sel0, sel1, sel2, sel3, sel4, sel5, type0, arg0, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \ 223 | MSMessage_(extra, type, _class, name, sel0 ## $ ## sel1 ## $ ## sel2 ## $ ## sel3 ## $ ## sel4 ## $ ## sel5 ## $, sel0:sel1:sel2:sel3:sel4:sel5:, (_cls, _old, _spr, self, _cmd, arg0, arg1, arg2, arg3, arg4, arg5), type0 arg0, type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) 224 | 225 | #define MSInstanceMessage0(type, _class, args...) MSMessage0_(MSIgnore_, type, _class *, _class, ## args) 226 | #define MSInstanceMessage1(type, _class, args...) MSMessage1_(MSIgnore_, type, _class *, _class, ## args) 227 | #define MSInstanceMessage2(type, _class, args...) MSMessage2_(MSIgnore_, type, _class *, _class, ## args) 228 | #define MSInstanceMessage3(type, _class, args...) MSMessage3_(MSIgnore_, type, _class *, _class, ## args) 229 | #define MSInstanceMessage4(type, _class, args...) MSMessage4_(MSIgnore_, type, _class *, _class, ## args) 230 | #define MSInstanceMessage5(type, _class, args...) MSMessage5_(MSIgnore_, type, _class *, _class, ## args) 231 | #define MSInstanceMessage6(type, _class, args...) MSMessage6_(MSIgnore_, type, _class *, _class, ## args) 232 | 233 | #define MSClassMessage0(type, _class, args...) MSMessage0_(MSIgnore_, type, Class, $ ## _class, ## args) 234 | #define MSClassMessage1(type, _class, args...) MSMessage1_(MSIgnore_, type, Class, $ ## _class, ## args) 235 | #define MSClassMessage2(type, _class, args...) MSMessage2_(MSIgnore_, type, Class, $ ## _class, ## args) 236 | #define MSClassMessage3(type, _class, args...) MSMessage3_(MSIgnore_, type, Class, $ ## _class, ## args) 237 | #define MSClassMessage4(type, _class, args...) MSMessage4_(MSIgnore_, type, Class, $ ## _class, ## args) 238 | #define MSClassMessage5(type, _class, args...) MSMessage5_(MSIgnore_, type, Class, $ ## _class, ## args) 239 | #define MSClassMessage6(type, _class, args...) MSMessage6_(MSIgnore_, type, Class, $ ## _class, ## args) 240 | 241 | #define MSInstanceMessageHook0(type, _class, args...) MSMessage0_(MSRegister_, type, _class *, _class, ## args) 242 | #define MSInstanceMessageHook1(type, _class, args...) MSMessage1_(MSRegister_, type, _class *, _class, ## args) 243 | #define MSInstanceMessageHook2(type, _class, args...) MSMessage2_(MSRegister_, type, _class *, _class, ## args) 244 | #define MSInstanceMessageHook3(type, _class, args...) MSMessage3_(MSRegister_, type, _class *, _class, ## args) 245 | #define MSInstanceMessageHook4(type, _class, args...) MSMessage4_(MSRegister_, type, _class *, _class, ## args) 246 | #define MSInstanceMessageHook5(type, _class, args...) MSMessage5_(MSRegister_, type, _class *, _class, ## args) 247 | #define MSInstanceMessageHook6(type, _class, args...) MSMessage6_(MSRegister_, type, _class *, _class, ## args) 248 | 249 | #define MSClassMessageHook0(type, _class, args...) MSMessage0_(MSRegister_, type, Class, $ ## _class, ## args) 250 | #define MSClassMessageHook1(type, _class, args...) MSMessage1_(MSRegister_, type, Class, $ ## _class, ## args) 251 | #define MSClassMessageHook2(type, _class, args...) MSMessage2_(MSRegister_, type, Class, $ ## _class, ## args) 252 | #define MSClassMessageHook3(type, _class, args...) MSMessage3_(MSRegister_, type, Class, $ ## _class, ## args) 253 | #define MSClassMessageHook4(type, _class, args...) MSMessage4_(MSRegister_, type, Class, $ ## _class, ## args) 254 | #define MSClassMessageHook5(type, _class, args...) MSMessage5_(MSRegister_, type, Class, $ ## _class, ## args) 255 | #define MSClassMessageHook6(type, _class, args...) MSMessage6_(MSRegister_, type, Class, $ ## _class, ## args) 256 | 257 | #define MSOldCall(args...) \ 258 | _old(self, _cmd, ## args) 259 | #define MSSuperCall(args...) \ 260 | _spr(& (struct objc_super) {self, class_getSuperclass(_cls)}, _cmd, ## args) 261 | 262 | #define MSIvarHook(type, name) \ 263 | type &name(MSHookIvar(self, #name)) 264 | 265 | #define MSClassHook(name) \ 266 | @class name; \ 267 | static Class $ ## name = objc_getClass(#name); 268 | #define MSMetaClassHook(name) \ 269 | @class name; \ 270 | static Class $$ ## name = object_getClass($ ## name); 271 | 272 | #endif/*__APPLE__*/ 273 | 274 | template 275 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) { 276 | return MSHookFunction( 277 | reinterpret_cast(symbol), 278 | reinterpret_cast(replace), 279 | reinterpret_cast(result) 280 | ); 281 | } 282 | 283 | template 284 | static inline void MSHookFunction(Type_ *symbol, Type_ *replace) { 285 | return MSHookFunction(symbol, replace, reinterpret_cast(NULL)); 286 | } 287 | 288 | template 289 | static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) { 290 | value = reinterpret_cast(MSFindSymbol(image, name)); 291 | } 292 | 293 | template 294 | static inline void MSHookFunction(const char *name, Type_ *replace, Type_ **result = NULL) { 295 | Type_ *symbol; 296 | MSHookSymbol(symbol, name); 297 | return MSHookFunction(symbol, replace, result); 298 | } 299 | 300 | #endif 301 | 302 | #define MSHook(type, name, args...) \ 303 | _disused static type (*_ ## name)(args); \ 304 | static type $ ## name(args) 305 | 306 | #ifdef __cplusplus 307 | #define MSHake(name) \ 308 | &$ ## name, &_ ## name 309 | #else 310 | #define MSHake(name) \ 311 | &$ ## name, (void **) &_ ## name 312 | #endif 313 | 314 | #define MSInitialize \ 315 | __attribute__((__constructor__)) static void _MSInitialize(void) 316 | 317 | #define Foundation_f "/System/Library/Frameworks/Foundation.framework/Foundation" 318 | #define UIKit_f "/System/Library/Frameworks/UIKit.framework/UIKit" 319 | #define JavaScriptCore_f "/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore" 320 | #define IOKit_f "/System/Library/Frameworks/IOKit.framework/IOKit" 321 | 322 | #endif//SUBSTRATE_H_ 323 | -------------------------------------------------------------------------------- /libs/fmod.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteandahalf/GenericLauncher/bc8a2a3e0c14b4dc5750f47fb2949b812c95bcd8/libs/fmod.jar -------------------------------------------------------------------------------- /prebuilts/tinysubstrate-bin/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | LOCAL_MODULE := tinysubstrate-bin 5 | LOCAL_SRC_FILES := libgenericlauncher_tinysubstrate.so 6 | include $(PREBUILT_SHARED_LIBRARY) -------------------------------------------------------------------------------- /prebuilts/tinysubstrate-bin/libgenericlauncher_tinysubstrate.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteandahalf/GenericLauncher/bc8a2a3e0c14b4dc5750f47fb2949b812c95bcd8/prebuilts/tinysubstrate-bin/libgenericlauncher_tinysubstrate.so -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-22 15 | 16 | android.library=false 17 | -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteandahalf/GenericLauncher/bc8a2a3e0c14b4dc5750f47fb2949b812c95bcd8/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteandahalf/GenericLauncher/bc8a2a3e0c14b4dc5750f47fb2949b812c95bcd8/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteandahalf/GenericLauncher/bc8a2a3e0c14b4dc5750f47fb2949b812c95bcd8/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteandahalf/GenericLauncher/bc8a2a3e0c14b4dc5750f47fb2949b812c95bcd8/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/layout/testbutton.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 |