Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
355341f0
Commit
355341f0
authored
Feb 02, 2022
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use AppComponentFactory to replace ClassLoader
parent
7f65f7d3
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
138 additions
and
82 deletions
+138
-82
DynAPK.java
app/shared/src/main/java/com/topjohnwu/magisk/DynAPK.java
+19
-7
ClassLoaders.java
stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java
+12
-0
DelegateApplication.java
...c/main/java/com/topjohnwu/magisk/DelegateApplication.java
+1
-11
DelegateComponentFactory.java
...n/java/com/topjohnwu/magisk/DelegateComponentFactory.java
+12
-7
DelegateRootService.java
...c/main/java/com/topjohnwu/magisk/DelegateRootService.java
+2
-5
DownloadActivity.java
.../src/main/java/com/topjohnwu/magisk/DownloadActivity.java
+1
-2
DynLoad.java
stub/src/main/java/com/topjohnwu/magisk/DynLoad.java
+91
-50
No files found.
app/shared/src/main/java/com/topjohnwu/magisk/DynAPK.java
View file @
355341f0
...
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk;
...
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk;
import
static
android
.
os
.
Build
.
VERSION
.
SDK_INT
;
import
static
android
.
os
.
Build
.
VERSION
.
SDK_INT
;
import
android.content.Context
;
import
android.content.Context
;
import
android.content.pm.ApplicationInfo
;
import
android.content.res.AssetManager
;
import
android.content.res.AssetManager
;
import
java.io.File
;
import
java.io.File
;
...
@@ -16,24 +17,35 @@ public class DynAPK {
...
@@ -16,24 +17,35 @@ public class DynAPK {
private
static
File
dynDir
;
private
static
File
dynDir
;
private
static
Method
addAssetPath
;
private
static
Method
addAssetPath
;
private
static
File
getDynDir
(
Context
c
)
{
private
static
File
getDynDir
(
ApplicationInfo
info
)
{
if
(
dynDir
==
null
)
{
if
(
dynDir
==
null
)
{
final
String
dataDir
;
if
(
SDK_INT
>=
24
)
{
if
(
SDK_INT
>=
24
)
{
// Use protected context to allow directBootAware
// Use device protected path to allow directBootAware
c
=
c
.
createDeviceProtectedStorageContext
();
dataDir
=
info
.
deviceProtectedDataDir
;
}
else
{
dataDir
=
info
.
dataDir
;
}
}
dynDir
=
new
File
(
c
.
getFilesDir
().
getParent
()
,
"dyn"
);
dynDir
=
new
File
(
dataDir
,
"dyn"
);
dynDir
.
mkdir
();
dynDir
.
mkdir
s
();
}
}
return
dynDir
;
return
dynDir
;
}
}
public
static
File
current
(
Context
c
)
{
public
static
File
current
(
Context
c
)
{
return
new
File
(
getDynDir
(
c
),
"current.apk"
);
return
new
File
(
getDynDir
(
c
.
getApplicationInfo
()),
"current.apk"
);
}
public
static
File
current
(
ApplicationInfo
info
)
{
return
new
File
(
getDynDir
(
info
),
"current.apk"
);
}
}
public
static
File
update
(
Context
c
)
{
public
static
File
update
(
Context
c
)
{
return
new
File
(
getDynDir
(
c
),
"update.apk"
);
return
new
File
(
getDynDir
(
c
.
getApplicationInfo
()),
"update.apk"
);
}
public
static
File
update
(
ApplicationInfo
info
)
{
return
new
File
(
getDynDir
(
info
),
"update.apk"
);
}
}
public
static
void
addAssetPath
(
AssetManager
asset
,
String
path
)
{
public
static
void
addAssetPath
(
AssetManager
asset
,
String
path
)
{
...
...
stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java
View file @
355341f0
...
@@ -30,3 +30,15 @@ class RedirectClassLoader extends ClassLoader {
...
@@ -30,3 +30,15 @@ class RedirectClassLoader extends ClassLoader {
return
clz
==
null
?
super
.
loadClass
(
name
,
resolve
)
:
clz
;
return
clz
==
null
?
super
.
loadClass
(
name
,
resolve
)
:
clz
;
}
}
}
}
class
DelegateClassLoader
extends
ClassLoader
{
DelegateClassLoader
()
{
super
(
null
);
}
@Override
protected
Class
<?>
loadClass
(
String
name
,
boolean
resolve
)
throws
ClassNotFoundException
{
return
DynLoad
.
loader
.
loadClass
(
name
);
}
}
stub/src/main/java/com/topjohnwu/magisk/DelegateApplication.java
View file @
355341f0
...
@@ -2,11 +2,8 @@ package com.topjohnwu.magisk;
...
@@ -2,11 +2,8 @@ package com.topjohnwu.magisk;
import
android.app.Application
;
import
android.app.Application
;
import
android.content.Context
;
import
android.content.Context
;
import
android.content.ContextWrapper
;
import
android.content.res.Configuration
;
import
android.content.res.Configuration
;
import
java.lang.reflect.Method
;
import
io.michaelrocks.paranoid.Obfuscate
;
import
io.michaelrocks.paranoid.Obfuscate
;
@Obfuscate
@Obfuscate
...
@@ -17,14 +14,7 @@ public class DelegateApplication extends Application {
...
@@ -17,14 +14,7 @@ public class DelegateApplication extends Application {
@Override
@Override
protected
void
attachBaseContext
(
Context
base
)
{
protected
void
attachBaseContext
(
Context
base
)
{
super
.
attachBaseContext
(
base
);
super
.
attachBaseContext
(
base
);
receiver
=
DynLoad
.
createAndSetupApp
(
this
);
receiver
=
DynLoad
.
setup
(
this
);
if
(
receiver
!=
null
)
try
{
// Call attachBaseContext without ContextImpl to show it is being wrapped
Method
m
=
ContextWrapper
.
class
.
getDeclaredMethod
(
"attachBaseContext"
,
Context
.
class
);
m
.
setAccessible
(
true
);
m
.
invoke
(
receiver
,
this
);
}
catch
(
Exception
ignored
)
{
/* Impossible */
}
}
}
@Override
@Override
...
...
stub/src/main/java/com/topjohnwu/magisk/DelegateComponentFactory.java
View file @
355341f0
...
@@ -8,20 +8,25 @@ import android.app.Service;
...
@@ -8,20 +8,25 @@ import android.app.Service;
import
android.content.BroadcastReceiver
;
import
android.content.BroadcastReceiver
;
import
android.content.ContentProvider
;
import
android.content.ContentProvider
;
import
android.content.Intent
;
import
android.content.Intent
;
import
android.content.pm.ApplicationInfo
;
@SuppressLint
(
"NewApi"
)
@SuppressLint
(
"NewApi"
)
public
class
DelegateComponentFactory
extends
AppComponentFactory
{
public
class
DelegateComponentFactory
extends
AppComponentFactory
{
ClassLoader
loader
;
AppComponentFactory
receiver
;
AppComponentFactory
receiver
;
public
DelegateComponentFactory
()
{
public
DelegateComponentFactory
()
{
DynLoad
.
componentFactory
=
this
;
DynLoad
.
componentFactory
=
this
;
}
}
@Override
public
ClassLoader
instantiateClassLoader
(
ClassLoader
cl
,
ApplicationInfo
info
)
{
DynLoad
.
loadAPK
(
info
);
return
new
DelegateClassLoader
();
}
@Override
@Override
public
Application
instantiateApplication
(
ClassLoader
cl
,
String
className
)
{
public
Application
instantiateApplication
(
ClassLoader
cl
,
String
className
)
{
if
(
loader
==
null
)
loader
=
cl
;
return
new
DelegateApplication
();
return
new
DelegateApplication
();
}
}
...
@@ -29,7 +34,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -29,7 +34,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
public
Activity
instantiateActivity
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
public
Activity
instantiateActivity
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateActivity
(
loader
,
className
,
intent
);
return
receiver
.
instantiateActivity
(
DynLoad
.
loader
,
className
,
intent
);
return
create
(
className
);
return
create
(
className
);
}
}
...
@@ -37,7 +42,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -37,7 +42,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
public
BroadcastReceiver
instantiateReceiver
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
public
BroadcastReceiver
instantiateReceiver
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateReceiver
(
loader
,
className
,
intent
);
return
receiver
.
instantiateReceiver
(
DynLoad
.
loader
,
className
,
intent
);
return
create
(
className
);
return
create
(
className
);
}
}
...
@@ -45,7 +50,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -45,7 +50,7 @@ public class DelegateComponentFactory extends AppComponentFactory {
public
Service
instantiateService
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
public
Service
instantiateService
(
ClassLoader
cl
,
String
className
,
Intent
intent
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateService
(
loader
,
className
,
intent
);
return
receiver
.
instantiateService
(
DynLoad
.
loader
,
className
,
intent
);
return
create
(
className
);
return
create
(
className
);
}
}
...
@@ -53,13 +58,13 @@ public class DelegateComponentFactory extends AppComponentFactory {
...
@@ -53,13 +58,13 @@ public class DelegateComponentFactory extends AppComponentFactory {
public
ContentProvider
instantiateProvider
(
ClassLoader
cl
,
String
className
)
public
ContentProvider
instantiateProvider
(
ClassLoader
cl
,
String
className
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
if
(
receiver
!=
null
)
if
(
receiver
!=
null
)
return
receiver
.
instantiateProvider
(
loader
,
className
);
return
receiver
.
instantiateProvider
(
DynLoad
.
loader
,
className
);
return
create
(
className
);
return
create
(
className
);
}
}
private
<
T
>
T
create
(
String
name
)
private
<
T
>
T
create
(
String
name
)
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
throws
ClassNotFoundException
,
IllegalAccessException
,
InstantiationException
{
return
(
T
)
loader
.
loadClass
(
name
).
newInstance
();
return
(
T
)
DynLoad
.
loader
.
loadClass
(
name
).
newInstance
();
}
}
}
}
stub/src/main/java/com/topjohnwu/magisk/DelegateRootService.java
View file @
355341f0
...
@@ -5,7 +5,6 @@ import android.content.ContextWrapper;
...
@@ -5,7 +5,6 @@ import android.content.ContextWrapper;
import
android.util.Log
;
import
android.util.Log
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Method
;
import
io.michaelrocks.paranoid.Obfuscate
;
import
io.michaelrocks.paranoid.Obfuscate
;
...
@@ -18,7 +17,7 @@ public class DelegateRootService extends ContextWrapper {
...
@@ -18,7 +17,7 @@ public class DelegateRootService extends ContextWrapper {
@Override
@Override
protected
void
attachBaseContext
(
Context
base
)
{
protected
void
attachBaseContext
(
Context
base
)
{
if
(
DynLoad
.
inject
(
base
)
==
null
)
if
(
DynLoad
.
createApp
(
base
)
==
null
)
return
;
return
;
// Create the actual RootService and call its attachBaseContext
// Create the actual RootService and call its attachBaseContext
...
@@ -26,9 +25,7 @@ public class DelegateRootService extends ContextWrapper {
...
@@ -26,9 +25,7 @@ public class DelegateRootService extends ContextWrapper {
Constructor
<?>
ctor
=
DynLoad
.
apkData
.
getRootService
().
getConstructor
(
Object
.
class
);
Constructor
<?>
ctor
=
DynLoad
.
apkData
.
getRootService
().
getConstructor
(
Object
.
class
);
ctor
.
setAccessible
(
true
);
ctor
.
setAccessible
(
true
);
Object
service
=
ctor
.
newInstance
(
this
);
Object
service
=
ctor
.
newInstance
(
this
);
Method
m
=
ContextWrapper
.
class
.
getDeclaredMethod
(
"attachBaseContext"
,
Context
.
class
);
DynLoad
.
attachContext
(
service
,
base
);
m
.
setAccessible
(
true
);
m
.
invoke
(
service
,
base
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Log
.
e
(
DelegateRootService
.
class
.
getSimpleName
(),
""
,
e
);
Log
.
e
(
DelegateRootService
.
class
.
getSimpleName
(),
""
,
e
);
}
}
...
...
stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java
View file @
355341f0
...
@@ -118,8 +118,7 @@ public class DownloadActivity extends Activity {
...
@@ -118,8 +118,7 @@ public class DownloadActivity extends Activity {
File
apk
=
dynLoad
?
DynAPK
.
current
(
this
)
:
new
File
(
getCacheDir
(),
"manager.apk"
);
File
apk
=
dynLoad
?
DynAPK
.
current
(
this
)
:
new
File
(
getCacheDir
(),
"manager.apk"
);
request
(
apkLink
).
setExecutor
(
AsyncTask
.
THREAD_POOL_EXECUTOR
).
getAsFile
(
apk
,
file
->
{
request
(
apkLink
).
setExecutor
(
AsyncTask
.
THREAD_POOL_EXECUTOR
).
getAsFile
(
apk
,
file
->
{
if
(
dynLoad
)
{
if
(
dynLoad
)
{
DynLoad
.
setup
(
this
);
// TODO
runOnUiThread
(
onSuccess
);
}
else
{
}
else
{
var
receiver
=
APKInstall
.
register
(
this
,
BuildConfig
.
APPLICATION_ID
,
onSuccess
);
var
receiver
=
APKInstall
.
register
(
this
,
BuildConfig
.
APPLICATION_ID
,
onSuccess
);
APKInstall
.
installapk
(
this
,
file
);
APKInstall
.
installapk
(
this
,
file
);
...
...
stub/src/main/java/com/topjohnwu/magisk/DynLoad.java
View file @
355341f0
...
@@ -2,7 +2,6 @@ package com.topjohnwu.magisk;
...
@@ -2,7 +2,6 @@ package com.topjohnwu.magisk;
import
android.app.AppComponentFactory
;
import
android.app.AppComponentFactory
;
import
android.app.Application
;
import
android.app.Application
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.content.Context
;
import
android.content.ContextWrapper
;
import
android.content.ContextWrapper
;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.ApplicationInfo
;
...
@@ -10,6 +9,7 @@ import android.content.pm.PackageInfo;
...
@@ -10,6 +9,7 @@ import android.content.pm.PackageInfo;
import
android.content.pm.PackageManager
;
import
android.content.pm.PackageManager
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Build
;
import
android.os.Environment
;
import
android.util.Log
;
import
android.util.Log
;
import
com.topjohnwu.magisk.utils.APKInstall
;
import
com.topjohnwu.magisk.utils.APKInstall
;
...
@@ -20,6 +20,7 @@ import java.io.FileOutputStream;
...
@@ -20,6 +20,7 @@ import java.io.FileOutputStream;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Method
;
import
io.michaelrocks.paranoid.Obfuscate
;
import
io.michaelrocks.paranoid.Obfuscate
;
...
@@ -27,23 +28,52 @@ import io.michaelrocks.paranoid.Obfuscate;
...
@@ -27,23 +28,52 @@ import io.michaelrocks.paranoid.Obfuscate;
@SuppressWarnings
(
"ResultOfMethodCallIgnored"
)
@SuppressWarnings
(
"ResultOfMethodCallIgnored"
)
public
class
DynLoad
{
public
class
DynLoad
{
// The current active classloader
static
ClassLoader
loader
=
new
RedirectClassLoader
();
static
Object
componentFactory
;
static
Object
componentFactory
;
static
final
DynAPK
.
Data
apkData
=
createApkData
();
static
final
DynAPK
.
Data
apkData
=
createApkData
();
// Dynamically load APK, inject ClassLoader into ContextImpl, then
private
static
boolean
loadedApk
=
false
;
// create the actual Application instance from the loaded APK
static
Application
inject
(
Context
context
)
{
static
void
attachContext
(
Object
o
,
Context
context
)
{
File
apk
=
DynAPK
.
current
(
context
);
if
(!(
o
instanceof
ContextWrapper
))
File
update
=
DynAPK
.
update
(
context
);
return
;
try
{
Method
m
=
ContextWrapper
.
class
.
getDeclaredMethod
(
"attachBaseContext"
,
Context
.
class
);
m
.
setAccessible
(
true
);
m
.
invoke
(
o
,
context
);
}
catch
(
Exception
ignored
)
{
/* Impossible */
}
}
// Dynamically load APK from internal or external storage
static
void
loadAPK
(
ApplicationInfo
info
)
{
if
(
loadedApk
)
return
;
loadedApk
=
true
;
File
apk
=
DynAPK
.
current
(
info
);
File
update
=
DynAPK
.
update
(
info
);
if
(
update
.
exists
())
{
if
(
update
.
exists
())
{
// Rename from update
// Rename from update
update
.
renameTo
(
apk
);
update
.
renameTo
(
apk
);
}
}
if
(
BuildConfig
.
DEBUG
)
{
// Copy from external for easier development
// Copy from external for easier development
if
(
BuildConfig
.
DEBUG
)
copy_from_ext:
{
File
external
=
new
File
(
context
.
getExternalFilesDir
(
null
),
"magisk.apk"
);
final
File
dir
;
try
{
var
dirs
=
(
File
[])
Environment
.
class
.
getMethod
(
"buildExternalStorageAppFilesDirs"
,
String
.
class
)
.
invoke
(
null
,
info
.
packageName
);
if
(
dirs
==
null
)
break
copy_from_ext
;
dir
=
dirs
[
0
];
}
catch
(
ReflectiveOperationException
e
)
{
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
break
copy_from_ext
;
}
File
external
=
new
File
(
dir
,
"magisk.apk"
);
if
(
external
.
exists
())
{
if
(
external
.
exists
())
{
try
{
try
{
var
in
=
new
FileInputStream
(
external
);
var
in
=
new
FileInputStream
(
external
);
...
@@ -60,19 +90,33 @@ public class DynLoad {
...
@@ -60,19 +90,33 @@ public class DynLoad {
}
}
}
}
if
(!
apk
.
exists
()
&&
!
context
.
getPackageName
().
equals
(
BuildConfig
.
APPLICATION_ID
))
{
if
(
apk
.
exists
())
{
// Copy from previous app
loader
=
new
InjectedClassLoader
(
apk
);
}
}
// Dynamically load APK, inject ClassLoader into ContextImpl, then
// create the non-stub Application instance from the loaded APK
static
Application
createApp
(
Context
context
)
{
File
apk
=
DynAPK
.
current
(
context
);
loadAPK
(
context
.
getApplicationInfo
());
// Trigger folder creation
context
.
getExternalFilesDir
(
null
);
// If no APK to load, attempt to copy from previous app
if
(!
isDynLoader
()
&&
!
context
.
getPackageName
().
equals
(
BuildConfig
.
APPLICATION_ID
))
{
Uri
uri
=
new
Uri
.
Builder
().
scheme
(
"content"
)
Uri
uri
=
new
Uri
.
Builder
().
scheme
(
"content"
)
.
authority
(
"com.topjohnwu.magisk.provider"
)
.
authority
(
"com.topjohnwu.magisk.provider"
)
.
encodedPath
(
"apk_file"
).
build
();
.
encodedPath
(
"apk_file"
).
build
();
ContentResolver
resolver
=
context
.
getContentResolver
();
try
{
try
{
InputStream
src
=
resolver
.
openInputStream
(
uri
);
InputStream
src
=
context
.
getContentResolver
()
.
openInputStream
(
uri
);
if
(
src
!=
null
)
{
if
(
src
!=
null
)
{
var
out
=
new
FileOutputStream
(
apk
);
var
out
=
new
FileOutputStream
(
apk
);
try
(
src
;
out
)
{
try
(
src
;
out
)
{
APKInstall
.
transfer
(
src
,
out
);
APKInstall
.
transfer
(
src
,
out
);
}
}
loader
=
new
InjectedClassLoader
(
apk
);
}
}
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
...
@@ -80,12 +124,11 @@ public class DynLoad {
...
@@ -80,12 +124,11 @@ public class DynLoad {
}
}
}
}
if
(
apk
.
exists
())
{
if
(
isDynLoader
())
{
ClassLoader
cl
=
new
InjectedClassLoader
(
apk
);
PackageManager
pm
=
context
.
getPackageManager
();
PackageManager
pm
=
context
.
getPackageManager
();
PackageInfo
pkgInfo
=
pm
.
getPackageArchiveInfo
(
apk
.
getPath
(),
0
);
PackageInfo
pkgInfo
=
pm
.
getPackageArchiveInfo
(
apk
.
getPath
(),
0
);
try
{
try
{
return
createApp
(
context
,
cl
,
pkgInfo
.
applicationInfo
);
return
newApp
(
pkgInfo
.
applicationInfo
);
}
catch
(
ReflectiveOperationException
e
)
{
}
catch
(
ReflectiveOperationException
e
)
{
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
apk
.
delete
();
apk
.
delete
();
...
@@ -95,65 +138,63 @@ public class DynLoad {
...
@@ -95,65 +138,63 @@ public class DynLoad {
return
null
;
return
null
;
}
}
// Inject and create Application, or setup redirections for the current app
// Stub app setup entry
static
Application
setup
(
Context
context
)
{
static
Application
createAndSetupApp
(
Application
context
)
{
Application
app
=
inject
(
context
);
// On API >= 29, AppComponentFactory will replace the ClassLoader
if
(
app
!=
null
)
{
if
(
Build
.
VERSION
.
SDK_INT
<
29
)
return
app
;
replaceClassLoader
(
context
);
}
ClassLoader
cl
=
new
RedirectClassLoader
();
Application
app
=
createApp
(
context
);
try
{
if
(
app
!=
null
)
{
setClassLoader
(
context
,
cl
);
// Send real application to attachBaseContext
if
(
Build
.
VERSION
.
SDK_INT
>=
28
)
{
attachContext
(
app
,
context
);
((
DelegateComponentFactory
)
componentFactory
).
loader
=
cl
;
}
}
catch
(
Exception
e
)
{
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
}
}
return
app
;
}
return
null
;
private
static
boolean
isDynLoader
()
{
return
loader
instanceof
InjectedClassLoader
;
}
}
private
static
Application
createApp
(
Context
context
,
ClassLoader
cl
,
ApplicationInfo
info
)
private
static
Application
newApp
(
ApplicationInfo
info
)
throws
ReflectiveOperationException
{
throws
ReflectiveOperationException
{
// Create the receiver Application
// Create the receiver Application
Object
app
=
cl
.
loadClass
(
info
.
className
)
var
app
=
(
Application
)
loader
.
loadClass
(
info
.
className
)
.
getConstructor
(
Object
.
class
)
.
getConstructor
(
Object
.
class
)
.
newInstance
(
apkData
.
getObject
());
.
newInstance
(
apkData
.
getObject
());
// Create the receiver component factory
// Create the receiver component factory
if
(
Build
.
VERSION
.
SDK_INT
>=
28
&&
componentFactory
!=
null
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
28
&&
componentFactory
!=
null
)
{
Object
factory
=
cl
.
loadClass
(
info
.
appComponentFactory
).
newInstance
();
Object
factory
=
loader
.
loadClass
(
info
.
appComponentFactory
).
newInstance
();
DelegateComponentFactory
delegate
=
(
DelegateComponentFactory
)
componentFactory
;
var
delegate
=
(
DelegateComponentFactory
)
componentFactory
;
delegate
.
loader
=
cl
;
delegate
.
receiver
=
(
AppComponentFactory
)
factory
;
delegate
.
receiver
=
(
AppComponentFactory
)
factory
;
}
}
setClassLoader
(
context
,
cl
);
return
app
;
return
(
Application
)
app
;
}
}
// Replace LoadedApk mClassLoader
// Replace LoadedApk mClassLoader
private
static
void
setClassLoader
(
Context
context
,
ClassLoader
cl
)
private
static
void
replaceClassLoader
(
Context
context
)
{
throws
NoSuchFieldException
,
IllegalAccessException
{
// Get ContextImpl
// Get ContextImpl
while
(
context
instanceof
ContextWrapper
)
{
while
(
context
instanceof
ContextWrapper
)
{
context
=
((
ContextWrapper
)
context
).
getBaseContext
();
context
=
((
ContextWrapper
)
context
).
getBaseContext
();
}
}
Field
mInfo
=
context
.
getClass
().
getDeclaredField
(
"mPackageInfo"
);
try
{
mInfo
.
setAccessible
(
true
);
Field
mInfo
=
context
.
getClass
().
getDeclaredField
(
"mPackageInfo"
);
Object
loadedApk
=
mInfo
.
get
(
context
);
mInfo
.
setAccessible
(
true
);
assert
loadedApk
!=
null
;
Object
loadedApk
=
mInfo
.
get
(
context
);
Field
mcl
=
loadedApk
.
getClass
().
getDeclaredField
(
"mClassLoader"
);
Field
mcl
=
loadedApk
.
getClass
().
getDeclaredField
(
"mClassLoader"
);
mcl
.
setAccessible
(
true
);
mcl
.
setAccessible
(
true
);
mcl
.
set
(
loadedApk
,
cl
);
mcl
.
set
(
loadedApk
,
new
DelegateClassLoader
());
}
catch
(
Exception
e
)
{
// Actually impossible as this method is only called on API < 29,
// and API 21 - 28 do not restrict access to these methods/fields.
Log
.
e
(
DynLoad
.
class
.
getSimpleName
(),
""
,
e
);
}
}
}
private
static
DynAPK
.
Data
createApkData
()
{
private
static
DynAPK
.
Data
createApkData
()
{
DynAPK
.
Data
data
=
new
DynAPK
.
Data
();
var
data
=
new
DynAPK
.
Data
();
data
.
setVersion
(
BuildConfig
.
STUB_VERSION
);
data
.
setVersion
(
BuildConfig
.
STUB_VERSION
);
data
.
setClassToComponent
(
Mapping
.
inverseMap
);
data
.
setClassToComponent
(
Mapping
.
inverseMap
);
data
.
setRootService
(
DelegateRootService
.
class
);
data
.
setRootService
(
DelegateRootService
.
class
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment