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
9ac71ff8
Commit
9ac71ff8
authored
Aug 01, 2018
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify asynchronous tasks
parent
075737a4
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
323 additions
and
305 deletions
+323
-305
MagiskFragment.java
app/src/full/java/com/topjohnwu/magisk/MagiskFragment.java
+1
-1
MagiskManager.java
app/src/full/java/com/topjohnwu/magisk/MagiskManager.java
+0
-5
ModulesFragment.java
app/src/full/java/com/topjohnwu/magisk/ModulesFragment.java
+6
-5
ReposFragment.java
app/src/full/java/com/topjohnwu/magisk/ReposFragment.java
+21
-14
SettingsActivity.java
app/src/full/java/com/topjohnwu/magisk/SettingsActivity.java
+3
-3
SplashActivity.java
app/src/full/java/com/topjohnwu/magisk/SplashActivity.java
+10
-16
CheckUpdates.java
...c/full/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java
+25
-32
FlashZip.java
app/src/full/java/com/topjohnwu/magisk/asyncs/FlashZip.java
+2
-2
HideManager.java
...rc/full/java/com/topjohnwu/magisk/asyncs/HideManager.java
+0
-97
LoadModules.java
...rc/full/java/com/topjohnwu/magisk/asyncs/LoadModules.java
+0
-36
PatchAPK.java
app/src/full/java/com/topjohnwu/magisk/asyncs/PatchAPK.java
+153
-0
RestoreImages.java
.../full/java/com/topjohnwu/magisk/asyncs/RestoreImages.java
+0
-39
UpdateRepos.java
...rc/full/java/com/topjohnwu/magisk/asyncs/UpdateRepos.java
+44
-44
UninstallDialog.java
...java/com/topjohnwu/magisk/components/UninstallDialog.java
+17
-2
ManagerUpdate.java
...ll/java/com/topjohnwu/magisk/receivers/ManagerUpdate.java
+10
-8
UpdateCheckService.java
...ava/com/topjohnwu/magisk/services/UpdateCheckService.java
+1
-1
Topic.java
app/src/full/java/com/topjohnwu/magisk/utils/Topic.java
+10
-0
Utils.java
app/src/full/java/com/topjohnwu/magisk/utils/Utils.java
+20
-0
No files found.
app/src/full/java/com/topjohnwu/magisk/MagiskFragment.java
View file @
9ac71ff8
...
...
@@ -172,7 +172,7 @@ public class MagiskFragment extends BaseFragment
// Trigger state check
if
(
Download
.
checkNetworkStatus
(
mm
))
{
new
CheckUpdates
().
exec
();
CheckUpdates
.
check
();
}
else
{
mSwipeRefreshLayout
.
setRefreshing
(
false
);
}
...
...
app/src/full/java/com/topjohnwu/magisk/MagiskManager.java
View file @
9ac71ff8
...
...
@@ -6,7 +6,6 @@ import android.content.res.Configuration;
import
android.preference.PreferenceManager
;
import
android.text.TextUtils
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.magisk.database.MagiskDatabaseHelper
;
import
com.topjohnwu.magisk.database.RepoDatabaseHelper
;
import
com.topjohnwu.magisk.utils.LocaleManager
;
...
...
@@ -15,16 +14,12 @@ import com.topjohnwu.superuser.ContainerApp;
import
com.topjohnwu.superuser.Shell
;
import
java.lang.ref.WeakReference
;
import
java.util.Map
;
public
class
MagiskManager
extends
ContainerApp
{
// Info
public
boolean
hasInit
=
false
;
// Data
public
Map
<
String
,
Module
>
moduleMap
;
// Global resources
public
SharedPreferences
prefs
;
public
MagiskDatabaseHelper
mDB
;
...
...
app/src/full/java/com/topjohnwu/magisk/ModulesFragment.java
View file @
9ac71ff8
...
...
@@ -17,14 +17,15 @@ import android.view.ViewGroup;
import
android.widget.TextView
;
import
com.topjohnwu.magisk.adapters.ModulesAdapter
;
import
com.topjohnwu.magisk.asyncs.LoadModules
;
import
com.topjohnwu.magisk.components.BaseFragment
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
butterknife.BindView
;
import
butterknife.ButterKnife
;
...
...
@@ -57,7 +58,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
mSwipeRefreshLayout
.
setOnRefreshListener
(()
->
{
recyclerView
.
setVisibility
(
View
.
GONE
);
new
LoadModules
().
exec
();
Utils
.
loadModules
();
});
recyclerView
.
addOnScrollListener
(
new
RecyclerView
.
OnScrollListener
()
{
...
...
@@ -84,7 +85,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
@Override
public
void
onPublish
(
int
topic
,
Object
[]
result
)
{
updateUI
();
updateUI
(
(
Map
<
String
,
Module
>)
result
[
0
]
);
}
@Override
...
...
@@ -128,9 +129,9 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
}
}
private
void
updateUI
()
{
private
void
updateUI
(
Map
<
String
,
Module
>
moduleMap
)
{
listModules
.
clear
();
listModules
.
addAll
(
m
m
.
m
oduleMap
.
values
());
listModules
.
addAll
(
moduleMap
.
values
());
if
(
listModules
.
size
()
==
0
)
{
emptyRv
.
setVisibility
(
View
.
VISIBLE
);
recyclerView
.
setVisibility
(
View
.
GONE
);
...
...
app/src/full/java/com/topjohnwu/magisk/ReposFragment.java
View file @
9ac71ff8
...
...
@@ -2,6 +2,7 @@ package com.topjohnwu.magisk;
import
android.app.AlertDialog
;
import
android.os.Bundle
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.support.v4.widget.SwipeRefreshLayout
;
import
android.support.v7.widget.RecyclerView
;
...
...
@@ -17,8 +18,11 @@ import android.widget.TextView;
import
com.topjohnwu.magisk.adapters.ReposAdapter
;
import
com.topjohnwu.magisk.asyncs.UpdateRepos
;
import
com.topjohnwu.magisk.components.BaseFragment
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.magisk.utils.Topic
;
import
java.util.Map
;
import
butterknife.BindView
;
import
butterknife.ButterKnife
;
import
butterknife.Unbinder
;
...
...
@@ -40,30 +44,24 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
@Nullable
@Override
public
View
onCreateView
(
LayoutInflater
inflater
,
@Nullable
ViewGroup
container
,
@Nullable
Bundle
savedInstanceState
)
{
public
View
onCreateView
(
@NonNull
LayoutInflater
inflater
,
@Nullable
ViewGroup
container
,
@Nullable
Bundle
savedInstanceState
)
{
View
view
=
inflater
.
inflate
(
R
.
layout
.
fragment_repos
,
container
,
false
);
unbinder
=
ButterKnife
.
bind
(
this
,
view
);
mSwipeRefreshLayout
.
setRefreshing
(
true
);
recyclerView
.
setVisibility
(
View
.
GONE
);
mSwipeRefreshLayout
.
setOnRefreshListener
(()
->
{
recyclerView
.
setVisibility
(
View
.
VISIBLE
);
emptyRv
.
setVisibility
(
View
.
GONE
);
new
UpdateRepos
(
true
).
exec
(
);
new
UpdateRepos
(
).
exec
(
true
);
});
get
Activity
().
setTitle
(
R
.
string
.
downloads
);
require
Activity
().
setTitle
(
R
.
string
.
downloads
);
return
view
;
}
@Override
public
void
onResume
()
{
adapter
=
new
ReposAdapter
(
mm
.
repoDB
,
mm
.
moduleMap
);
recyclerView
.
setAdapter
(
adapter
);
super
.
onResume
();
}
@Override
public
void
onPause
()
{
super
.
onPause
();
...
...
@@ -72,15 +70,24 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
@Override
public
int
[]
getSubscribedTopics
()
{
return
new
int
[]
{
Topic
.
REPO_LOAD_DONE
};
return
new
int
[]
{
Topic
.
MODULE_LOAD_DONE
,
Topic
.
REPO_LOAD_DONE
};
}
@Override
public
void
onPublish
(
int
topic
,
Object
[]
result
)
{
if
(
topic
==
Topic
.
MODULE_LOAD_DONE
)
{
adapter
=
new
ReposAdapter
(
mm
.
repoDB
,
(
Map
<
String
,
Module
>)
result
[
0
]);
recyclerView
.
setAdapter
(
adapter
);
recyclerView
.
setVisibility
(
View
.
VISIBLE
);
emptyRv
.
setVisibility
(
View
.
GONE
);
}
if
(
Topic
.
isPublished
(
getSubscribedTopics
()))
{
adapter
.
notifyDBChanged
();
mSwipeRefreshLayout
.
setRefreshing
(
false
);
recyclerView
.
setVisibility
(
adapter
.
getItemCount
()
==
0
?
View
.
GONE
:
View
.
VISIBLE
);
emptyRv
.
setVisibility
(
adapter
.
getItemCount
()
==
0
?
View
.
VISIBLE
:
View
.
GONE
);
}
}
@Override
public
void
onCreateOptionsMenu
(
Menu
menu
,
MenuInflater
inflater
)
{
...
...
app/src/full/java/com/topjohnwu/magisk/SettingsActivity.java
View file @
9ac71ff8
...
...
@@ -21,7 +21,7 @@ import android.widget.EditText;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.asyncs.CheckUpdates
;
import
com.topjohnwu.magisk.asyncs.
HideManager
;
import
com.topjohnwu.magisk.asyncs.
PatchAPK
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.receivers.DownloadReceiver
;
import
com.topjohnwu.magisk.utils.Download
;
...
...
@@ -163,7 +163,7 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber {
if
(
Data
.
magiskVersionCode
>=
Const
.
MAGISK_VER
.
MANAGER_HIDE
)
{
if
(
mm
.
getPackageName
().
equals
(
Const
.
ORIG_PKG_NAME
))
{
hideManager
.
setOnPreferenceClickListener
((
pref
)
->
{
new
HideManager
(
getActivity
()).
exec
(
);
PatchAPK
.
hideManager
(
requireActivity
()
);
return
true
;
});
generalCatagory
.
removePreference
(
restoreManager
);
...
...
@@ -287,7 +287,7 @@ public class SettingsActivity extends BaseActivity implements Topic.Subscriber {
Topic
.
publish
(
false
,
Topic
.
RELOAD_ACTIVITY
);
break
;
case
Const
.
Key
.
UPDATE_CHANNEL
:
new
CheckUpdates
().
exec
();
CheckUpdates
.
check
();
break
;
case
Const
.
Key
.
CHECK_UPDATES
:
Utils
.
setupUpdateCheck
();
...
...
app/src/full/java/com/topjohnwu/magisk/SplashActivity.java
View file @
9ac71ff8
...
...
@@ -7,7 +7,6 @@ import android.os.Build;
import
android.os.Bundle
;
import
com.topjohnwu.magisk.asyncs.CheckUpdates
;
import
com.topjohnwu.magisk.asyncs.LoadModules
;
import
com.topjohnwu.magisk.asyncs.UpdateRepos
;
import
com.topjohnwu.magisk.components.BaseActivity
;
import
com.topjohnwu.magisk.database.RepoDatabaseHelper
;
...
...
@@ -23,8 +22,13 @@ public class SplashActivity extends BaseActivity {
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
// Force create a shell if not created yet
boolean
root
=
Shell
.
rootAccess
();
// Magisk working as expected
if
(
Shell
.
rootAccess
()
&&
Data
.
magiskVersionCode
>
0
)
{
// Update check service
Utils
.
setupUpdateCheck
();
// Load modules
Utils
.
loadModules
();
}
mm
.
repoDB
=
new
RepoDatabaseHelper
(
this
);
Data
.
importPrefs
();
...
...
@@ -42,21 +46,11 @@ public class SplashActivity extends BaseActivity {
// Setup shortcuts
sendBroadcast
(
new
Intent
(
this
,
ShortcutReceiver
.
class
));
LoadModules
loadModuleTask
=
new
LoadModules
();
if
(
Download
.
checkNetworkStatus
(
this
))
{
// Fire update check
new
CheckUpdates
().
exec
();
// Add repo update check
loadModuleTask
.
setCallBack
(()
->
new
UpdateRepos
(
false
).
exec
());
}
// Magisk working as expected
if
(
root
&&
Data
.
magiskVersionCode
>
0
)
{
// Update check service
Utils
.
setupUpdateCheck
();
// Fire asynctasks
loadModuleTask
.
exec
();
CheckUpdates
.
check
();
// Repo update check
new
UpdateRepos
().
exec
();
}
// Write back default values
...
...
app/src/full/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java
View file @
9ac71ff8
package
com
.
topjohnwu
.
magisk
.
asyncs
;
import
android.os.AsyncTask
;
import
com.topjohnwu.magisk.BuildConfig
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.utils.NotificationMgr
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.magisk.utils.WebService
;
...
...
@@ -11,19 +12,9 @@ import com.topjohnwu.magisk.utils.WebService;
import
org.json.JSONException
;
import
org.json.JSONObject
;
public
class
CheckUpdates
extends
ParallelTask
<
Void
,
Void
,
Void
>
{
private
boolean
showNotification
;
public
CheckUpdates
()
{
this
(
false
);
}
public
CheckUpdates
(
boolean
b
)
{
showNotification
=
b
;
}
public
class
CheckUpdates
{
private
int
getInt
(
JSONObject
json
,
String
name
,
int
defValue
)
{
private
static
int
getInt
(
JSONObject
json
,
String
name
,
int
defValue
)
{
if
(
json
==
null
)
return
defValue
;
try
{
...
...
@@ -33,7 +24,7 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
}
}
private
String
getString
(
JSONObject
json
,
String
name
,
String
defValue
)
{
private
static
String
getString
(
JSONObject
json
,
String
name
,
String
defValue
)
{
if
(
json
==
null
)
return
defValue
;
try
{
...
...
@@ -43,7 +34,7 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
}
}
private
JSONObject
getJson
(
JSONObject
json
,
String
name
)
{
private
static
JSONObject
getJson
(
JSONObject
json
,
String
name
)
{
try
{
return
json
.
getJSONObject
(
name
);
}
catch
(
JSONException
e
)
{
...
...
@@ -51,9 +42,7 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
}
}
@Override
protected
Void
doInBackground
(
Void
...
voids
)
{
MagiskManager
mm
=
Data
.
MM
();
public
static
void
fetchUpdates
()
{
String
jsonStr
=
""
;
switch
(
Data
.
updateChannel
)
{
case
Const
.
Value
.
STABLE_CHANNEL
:
...
...
@@ -63,7 +52,7 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
jsonStr
=
WebService
.
getString
(
Const
.
Url
.
BETA_URL
);
break
;
case
Const
.
Value
.
CUSTOM_CHANNEL
:
jsonStr
=
WebService
.
getString
(
mm
.
prefs
.
getString
(
Const
.
Key
.
CUSTOM_CHANNEL
,
""
));
jsonStr
=
WebService
.
getString
(
Data
.
MM
()
.
prefs
.
getString
(
Const
.
Key
.
CUSTOM_CHANNEL
,
""
));
break
;
}
...
...
@@ -71,7 +60,7 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
try
{
json
=
new
JSONObject
(
jsonStr
);
}
catch
(
JSONException
e
)
{
return
null
;
return
;
}
JSONObject
magisk
=
getJson
(
json
,
"magisk"
);
...
...
@@ -88,20 +77,24 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
JSONObject
uninstaller
=
getJson
(
json
,
"uninstaller"
);
Data
.
uninstallerLink
=
getString
(
uninstaller
,
"link"
,
null
);
return
null
;
}
@Override
protected
void
onPostExecute
(
Void
v
)
{
if
(
showNotification
)
{
public
static
void
check
(
Runnable
cb
)
{
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
fetchUpdates
();
if
(
cb
!=
null
)
{
if
(
BuildConfig
.
VERSION_CODE
<
Data
.
remoteManagerVersionCode
)
{
NotificationMgr
.
managerUpdate
();
}
else
if
(
Data
.
magiskVersionCode
<
Data
.
remoteMagiskVersionCode
)
{
NotificationMgr
.
magiskUpdate
();
}
cb
.
run
();
}
Topic
.
publish
(
Topic
.
UPDATE_CHECK_DONE
);
super
.
onPostExecute
(
v
);
});
}
public
static
void
check
()
{
check
(
null
);
}
}
app/src/full/java/com/topjohnwu/magisk/asyncs/FlashZip.java
View file @
9ac71ff8
...
...
@@ -94,8 +94,8 @@ public class FlashZip extends ParallelTask<Void, Void, Integer> {
console
.
add
(
"! This zip is not a Magisk Module!"
);
break
;
case
1
:
//
Succes
s
new
LoadModules
().
exec
();
//
Reload module
s
Utils
.
loadModules
();
break
;
}
activity
.
reboot
.
setVisibility
(
result
>
0
?
View
.
VISIBLE
:
View
.
GONE
);
...
...
app/src/full/java/com/topjohnwu/magisk/asyncs/HideManager.java
deleted
100644 → 0
View file @
075737a4
package
com
.
topjohnwu
.
magisk
.
asyncs
;
import
android.app.Activity
;
import
android.app.ProgressDialog
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.PatchAPK
;
import
com.topjohnwu.magisk.utils.RootUtils
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
import
com.topjohnwu.superuser.ShellUtils
;
import
com.topjohnwu.superuser.io.SuFile
;
import
com.topjohnwu.superuser.io.SuFileOutputStream
;
import
java.io.FileNotFoundException
;
import
java.security.SecureRandom
;
public
class
HideManager
extends
ParallelTask
<
Void
,
Void
,
Boolean
>
{
private
ProgressDialog
dialog
;
public
HideManager
(
Activity
activity
)
{
super
(
activity
);
}
private
String
genPackageName
(
String
prefix
,
int
length
)
{
StringBuilder
builder
=
new
StringBuilder
(
length
);
builder
.
append
(
prefix
);
length
-=
prefix
.
length
();
SecureRandom
random
=
new
SecureRandom
();
String
base
=
"abcdefghijklmnopqrstuvwxyz"
;
String
alpha
=
base
+
base
.
toUpperCase
();
String
full
=
alpha
+
"0123456789.........."
;
char
next
,
prev
=
'\0'
;
for
(
int
i
=
0
;
i
<
length
;
++
i
)
{
if
(
prev
==
'.'
||
i
==
length
-
1
||
i
==
0
)
{
next
=
alpha
.
charAt
(
random
.
nextInt
(
alpha
.
length
()));
}
else
{
next
=
full
.
charAt
(
random
.
nextInt
(
full
.
length
()));
}
builder
.
append
(
next
);
prev
=
next
;
}
return
builder
.
toString
();
}
@Override
protected
void
onPreExecute
()
{
dialog
=
ProgressDialog
.
show
(
getActivity
(),
getActivity
().
getString
(
R
.
string
.
hide_manager_toast
),
getActivity
().
getString
(
R
.
string
.
hide_manager_toast2
));
}
@Override
protected
Boolean
doInBackground
(
Void
...
voids
)
{
MagiskManager
mm
=
Data
.
MM
();
// Generate a new app with random package name
SuFile
repack
=
new
SuFile
(
"/data/local/tmp/repack.apk"
);
String
pkg
=
genPackageName
(
"com."
,
Const
.
ORIG_PKG_NAME
.
length
());
try
{
if
(!
PatchAPK
.
patchPackageID
(
mm
.
getPackageCodePath
(),
new
SuFileOutputStream
(
repack
),
Const
.
ORIG_PKG_NAME
,
pkg
))
return
false
;
}
catch
(
FileNotFoundException
e
)
{
return
false
;
}
// Install the application
if
(!
ShellUtils
.
fastCmdResult
(
Shell
.
getShell
(),
"pm install "
+
repack
))
return
false
;
repack
.
delete
();
mm
.
mDB
.
setStrings
(
Const
.
Key
.
SU_MANAGER
,
pkg
);
Data
.
exportPrefs
();
RootUtils
.
uninstallPkg
(
Const
.
ORIG_PKG_NAME
);
return
true
;
}
@Override
protected
void
onPostExecute
(
Boolean
b
)
{
dialog
.
dismiss
();
if
(!
b
)
{
Utils
.
toast
(
R
.
string
.
hide_manager_fail_toast
,
Toast
.
LENGTH_LONG
);
}
super
.
onPostExecute
(
b
);
}
}
app/src/full/java/com/topjohnwu/magisk/asyncs/LoadModules.java
deleted
100644 → 0
View file @
075737a4
package
com
.
topjohnwu
.
magisk
.
asyncs
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.magisk.container.ValueSortedMap
;
import
com.topjohnwu.magisk.utils.Topic
;
import
com.topjohnwu.superuser.io.SuFile
;
public
class
LoadModules
extends
ParallelTask
<
Void
,
Void
,
Void
>
{
private
String
[]
getModList
()
{
SuFile
path
=
new
SuFile
(
Const
.
MAGISK_PATH
);
return
path
.
list
((
file
,
name
)
->
!
name
.
equals
(
"lost+found"
)
&&
!
name
.
equals
(
".core"
));
}
@Override
protected
Void
doInBackground
(
Void
...
voids
)
{
MagiskManager
mm
=
Data
.
MM
();
mm
.
moduleMap
=
new
ValueSortedMap
<>();
for
(
String
name
:
getModList
())
{
Module
module
=
new
Module
(
Const
.
MAGISK_PATH
+
"/"
+
name
);
mm
.
moduleMap
.
put
(
module
.
getId
(),
module
);
}
return
null
;
}
@Override
protected
void
onPostExecute
(
Void
v
)
{
Topic
.
publish
(
Topic
.
MODULE_LOAD_DONE
);
super
.
onPostExecute
(
v
);
}
}
app/src/full/java/com/topjohnwu/magisk/
util
s/PatchAPK.java
→
app/src/full/java/com/topjohnwu/magisk/
async
s/PatchAPK.java
View file @
9ac71ff8
package
com
.
topjohnwu
.
magisk
.
utils
;
package
com
.
topjohnwu
.
magisk
.
asyncs
;
import
android.app.Activity
;
import
android.app.ProgressDialog
;
import
android.os.AsyncTask
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.RootUtils
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.magisk.utils.ZipUtils
;
import
com.topjohnwu.superuser.ShellUtils
;
import
com.topjohnwu.superuser.io.SuFile
;
import
com.topjohnwu.superuser.io.SuFileOutputStream
;
import
com.topjohnwu.utils.JarMap
;
import
java.
io.OutputStrea
m
;
import
java.
security.SecureRando
m
;
import
java.util.jar.JarEntry
;
public
class
PatchAPK
{
private
static
String
genPackageName
(
String
prefix
,
int
length
)
{
StringBuilder
builder
=
new
StringBuilder
(
length
);
builder
.
append
(
prefix
);
length
-=
prefix
.
length
();
SecureRandom
random
=
new
SecureRandom
();
String
base
=
"abcdefghijklmnopqrstuvwxyz"
;
String
alpha
=
base
+
base
.
toUpperCase
();
String
full
=
alpha
+
"0123456789.........."
;
char
next
,
prev
=
'\0'
;
for
(
int
i
=
0
;
i
<
length
;
++
i
)
{
if
(
prev
==
'.'
||
i
==
length
-
1
||
i
==
0
)
{
next
=
alpha
.
charAt
(
random
.
nextInt
(
alpha
.
length
()));
}
else
{
next
=
full
.
charAt
(
random
.
nextInt
(
full
.
length
()));
}
builder
.
append
(
next
);
prev
=
next
;
}
return
builder
.
toString
();
}
private
static
int
findOffset
(
byte
buf
[],
byte
pattern
[])
{
int
offset
=
-
1
;
for
(
int
i
=
0
;
i
<
buf
.
length
-
pattern
.
length
;
++
i
)
{
...
...
@@ -53,9 +88,37 @@ public class PatchAPK {
return
true
;
}
public
static
boolean
patchPackageID
(
String
fileName
,
OutputStream
out
,
String
from
,
String
to
)
{
private
static
boolean
patchAndHide
()
{
MagiskManager
mm
=
Data
.
MM
();
// Generate a new app with random package name
SuFile
repack
=
new
SuFile
(
"/data/local/tmp/repack.apk"
);
String
pkg
=
genPackageName
(
"com."
,
Const
.
ORIG_PKG_NAME
.
length
());
try
{
JarMap
apk
=
new
JarMap
(
mm
.
getPackageCodePath
());
if
(!
patchPackageID
(
apk
,
Const
.
ORIG_PKG_NAME
,
pkg
))
return
false
;
ZipUtils
.
signZip
(
apk
,
new
SuFileOutputStream
(
repack
));
}
catch
(
Exception
e
)
{
return
false
;
}
// Install the application
if
(!
ShellUtils
.
fastCmdResult
(
"pm install "
+
repack
))
return
false
;
repack
.
delete
();
mm
.
mDB
.
setStrings
(
Const
.
Key
.
SU_MANAGER
,
pkg
);
Data
.
exportPrefs
();
RootUtils
.
uninstallPkg
(
Const
.
ORIG_PKG_NAME
);
return
true
;
}
public
static
boolean
patchPackageID
(
JarMap
apk
,
String
from
,
String
to
)
{
try
{
JarMap
apk
=
new
JarMap
(
fileName
);
JarEntry
je
=
apk
.
getJarEntry
(
Const
.
ANDROID_MANIFEST
);
byte
xml
[]
=
apk
.
getRawData
(
je
);
...
...
@@ -66,13 +129,25 @@ public class PatchAPK {
// Write in changes
apk
.
getOutputStream
(
je
).
write
(
xml
);
// Sign the APK
ZipUtils
.
signZip
(
apk
,
out
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
false
;
}
return
true
;
}
public
static
void
hideManager
(
Activity
activity
)
{
ProgressDialog
dialog
=
ProgressDialog
.
show
(
activity
,
activity
.
getString
(
R
.
string
.
hide_manager_toast
),
activity
.
getString
(
R
.
string
.
hide_manager_toast2
));
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
boolean
b
=
patchAndHide
();
Data
.
mainHandler
.
post
(()
->
{
dialog
.
cancel
();
if
(!
b
)
{
Utils
.
toast
(
R
.
string
.
hide_manager_fail_toast
,
Toast
.
LENGTH_LONG
);
}
});
});
}
}
app/src/full/java/com/topjohnwu/magisk/asyncs/RestoreImages.java
deleted
100644 → 0
View file @
075737a4
package
com
.
topjohnwu
.
magisk
.
asyncs
;
import
android.app.Activity
;
import
android.app.ProgressDialog
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.ShellUtils
;
public
class
RestoreImages
extends
ParallelTask
<
Void
,
Void
,
Boolean
>
{
private
ProgressDialog
dialog
;
public
RestoreImages
(
Activity
activity
)
{
super
(
activity
);
}
@Override
protected
void
onPreExecute
()
{
Activity
a
=
getActivity
();
dialog
=
ProgressDialog
.
show
(
a
,
a
.
getString
(
R
.
string
.
restore_img
),
a
.
getString
(
R
.
string
.
restore_img_msg
));
}
@Override
protected
Boolean
doInBackground
(
Void
...
voids
)
{
return
ShellUtils
.
fastCmdResult
(
"restore_imgs"
);
}
@Override
protected
void
onPostExecute
(
Boolean
result
)
{
dialog
.
cancel
();
if
(
result
)
{
Utils
.
toast
(
R
.
string
.
restore_done
,
Toast
.
LENGTH_SHORT
);
}
else
{
Utils
.
toast
(
R
.
string
.
restore_fail
,
Toast
.
LENGTH_LONG
);
}
}
}
app/src/full/java/com/topjohnwu/magisk/asyncs/UpdateRepos.java
View file @
9ac71ff8
package
com
.
topjohnwu
.
magisk
.
asyncs
;
import
android.database.Cursor
;
import
android.os.AsyncTask
;
import
android.text.TextUtils
;
import
com.topjohnwu.magisk.Const
;
...
...
@@ -34,7 +35,7 @@ import java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.TimeUnit
;
public
class
UpdateRepos
extends
ParallelTask
<
Void
,
Void
,
Void
>
{
public
class
UpdateRepos
{
private
static
final
int
CHECK_ETAG
=
0
;
private
static
final
int
LOAD_NEXT
=
1
;
...
...
@@ -44,16 +45,14 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
private
static
final
int
CORE_POOL_SIZE
=
Math
.
max
(
2
,
CPU_COUNT
-
1
);
private
MagiskManager
mm
;
private
List
<
String
>
etags
,
newEtags
=
new
LinkedList
<>()
;
private
List
<
String
>
etags
,
newEtags
;
private
Set
<
String
>
cached
;
private
boolean
forceUpdate
;
private
ExecutorService
threadPool
;
public
UpdateRepos
(
boolean
force
)
{
Topic
.
reset
(
Topic
.
REPO_LOAD_DONE
);
public
UpdateRepos
()
{
mm
=
Data
.
MM
();
forceUpdate
=
force
;
threadPool
=
Executors
.
newFixedThreadPool
(
CORE_POOL_SIZE
);
newEtags
=
new
LinkedList
<>();
}
private
void
waitTasks
()
{
...
...
@@ -85,7 +84,10 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
set
.
remove
(
id
);
repo
.
update
(
date
);
mm
.
repoDB
.
addRepo
(
repo
);
publishProgress
();
Data
.
mainHandler
.
post
(()
->
{
if
(
ReposFragment
.
adapter
!=
null
)
ReposFragment
.
adapter
.
notifyDBChanged
();
});
}
catch
(
Repo
.
IllegalRepoException
e
)
{
Logger
.
debug
(
e
.
getMessage
());
mm
.
repoDB
.
removeRepo
(
id
);
...
...
@@ -142,26 +144,7 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
return
true
;
}
@Override
protected
void
onProgressUpdate
(
Void
...
values
)
{
if
(
ReposFragment
.
adapter
!=
null
)
ReposFragment
.
adapter
.
notifyDBChanged
();
}
@Override
protected
Void
doInBackground
(
Void
...
voids
)
{
etags
=
Arrays
.
asList
(
mm
.
prefs
.
getString
(
Const
.
Key
.
ETAG_KEY
,
""
).
split
(
","
));
cached
=
mm
.
repoDB
.
getRepoIDSet
();
if
(
loadPage
(
0
,
CHECK_ETAG
))
{
waitTasks
();
// The leftover cached means they are removed from online repo
mm
.
repoDB
.
removeRepo
(
cached
);
// Update ETag
mm
.
prefs
.
edit
().
putString
(
Const
.
Key
.
ETAG_KEY
,
TextUtils
.
join
(
","
,
newEtags
)).
apply
();
}
else
if
(
forceUpdate
)
{
private
void
fullReload
()
{
Cursor
c
=
mm
.
repoDB
.
getRawCursor
();
while
(
c
.
moveToNext
())
{
Repo
repo
=
new
Repo
(
c
);
...
...
@@ -177,12 +160,29 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
}
waitTasks
();
}
return
null
;
}
@Override
protected
void
onPostExecute
(
Void
v
)
{
public
void
exec
(
boolean
force
)
{
Topic
.
reset
(
Topic
.
REPO_LOAD_DONE
);
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
etags
=
Arrays
.
asList
(
mm
.
prefs
.
getString
(
Const
.
Key
.
ETAG_KEY
,
""
).
split
(
","
));
cached
=
mm
.
repoDB
.
getRepoIDSet
();
if
(
loadPage
(
0
,
CHECK_ETAG
))
{
waitTasks
();
// The leftover cached means they are removed from online repo
mm
.
repoDB
.
removeRepo
(
cached
);
// Update ETag
mm
.
prefs
.
edit
().
putString
(
Const
.
Key
.
ETAG_KEY
,
TextUtils
.
join
(
","
,
newEtags
)).
apply
();
}
else
if
(
force
)
{
fullReload
();
}
Topic
.
publish
(
Topic
.
REPO_LOAD_DONE
);
super
.
onPostExecute
(
v
);
});
}
public
void
exec
()
{
exec
(
false
);
}
}
app/src/full/java/com/topjohnwu/magisk/components/UninstallDialog.java
View file @
9ac71ff8
package
com
.
topjohnwu
.
magisk
.
components
;
import
android.app.Activity
;
import
android.app.ProgressDialog
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.net.Uri
;
import
android.support.annotation.NonNull
;
import
android.text.TextUtils
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.FlashActivity
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.R
;
import
com.topjohnwu.magisk.asyncs.RestoreImages
;
import
com.topjohnwu.magisk.receivers.DownloadReceiver
;
import
com.topjohnwu.magisk.utils.Download
;
import
com.topjohnwu.magisk.utils.Utils
;
import
com.topjohnwu.superuser.Shell
;
public
class
UninstallDialog
extends
CustomAlertDialog
{
...
...
@@ -23,7 +26,19 @@ public class UninstallDialog extends CustomAlertDialog {
MagiskManager
mm
=
Data
.
MM
();
setTitle
(
R
.
string
.
uninstall_magisk_title
);
setMessage
(
R
.
string
.
uninstall_magisk_msg
);
setNeutralButton
(
R
.
string
.
restore_img
,
(
d
,
i
)
->
new
RestoreImages
(
activity
).
exec
());
setNeutralButton
(
R
.
string
.
restore_img
,
(
d
,
i
)
->
{
ProgressDialog
dialog
=
ProgressDialog
.
show
(
activity
,
activity
.
getString
(
R
.
string
.
restore_img
),
activity
.
getString
(
R
.
string
.
restore_img_msg
));
Shell
.
su
(
"restore_imgs"
).
submit
(
result
->
{
dialog
.
cancel
();
if
(
result
.
isSuccess
())
{
Utils
.
toast
(
R
.
string
.
restore_done
,
Toast
.
LENGTH_SHORT
);
}
else
{
Utils
.
toast
(
R
.
string
.
restore_fail
,
Toast
.
LENGTH_LONG
);
}
});
});
if
(!
TextUtils
.
isEmpty
(
Data
.
uninstallerLink
))
{
setPositiveButton
(
R
.
string
.
complete_uninstall
,
(
d
,
i
)
->
Download
.
receive
(
activity
,
new
DownloadReceiver
()
{
...
...
app/src/full/java/com/topjohnwu/magisk/receivers/ManagerUpdate.java
View file @
9ac71ff8
...
...
@@ -7,12 +7,13 @@ import android.net.Uri;
import
android.os.AsyncTask
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.asyncs.PatchAPK
;
import
com.topjohnwu.magisk.utils.Download
;
import
com.topjohnwu.magisk.utils.PatchAPK
;
import
com.topjohnwu.magisk.utils.ZipUtils
;
import
com.topjohnwu.utils.JarMap
;
import
java.io.BufferedOutputStream
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
public
class
ManagerUpdate
extends
BroadcastReceiver
{
...
...
@@ -31,13 +32,14 @@ public class ManagerUpdate extends BroadcastReceiver {
public
void
onDownloadDone
(
Context
context
,
Uri
uri
)
{
if
(!
context
.
getPackageName
().
equals
(
Const
.
ORIG_PKG_NAME
))
{
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
String
o
=
uri
.
getPath
();
String
p
=
o
.
substring
(
0
,
o
.
lastIndexOf
(
'.'
))
+
"-patched.apk"
;
String
o
rig
=
uri
.
getPath
();
String
p
atch
=
orig
.
substring
(
0
,
orig
.
lastIndexOf
(
'.'
))
+
"-patched.apk"
;
try
{
PatchAPK
.
patchPackageID
(
o
,
new
BufferedOutputStream
(
new
FileOutputStream
(
p
)),
Const
.
ORIG_PKG_NAME
,
context
.
getPackageName
());
}
catch
(
FileNotFoundException
ignored
)
{
}
super
.
onDownloadDone
(
context
,
Uri
.
fromFile
(
new
File
(
p
)));
JarMap
apk
=
new
JarMap
(
orig
);
PatchAPK
.
patchPackageID
(
apk
,
Const
.
ORIG_PKG_NAME
,
context
.
getPackageName
());
ZipUtils
.
signZip
(
apk
,
new
BufferedOutputStream
(
new
FileOutputStream
(
patch
)));
super
.
onDownloadDone
(
context
,
Uri
.
fromFile
(
new
File
(
patch
)));
}
catch
(
Exception
ignored
)
{
}
});
}
else
{
super
.
onDownloadDone
(
context
,
uri
);
...
...
app/src/full/java/com/topjohnwu/magisk/services/UpdateCheckService.java
View file @
9ac71ff8
...
...
@@ -11,7 +11,7 @@ public class UpdateCheckService extends JobService {
@Override
public
boolean
onStartJob
(
JobParameters
params
)
{
Shell
.
getShell
();
new
CheckUpdates
(
true
).
setCallBack
(()
->
jobFinished
(
params
,
false
)).
exec
(
);
CheckUpdates
.
check
(()
->
jobFinished
(
params
,
false
)
);
return
true
;
}
...
...
app/src/full/java/com/topjohnwu/magisk/utils/Topic.java
View file @
9ac71ff8
...
...
@@ -81,6 +81,16 @@ public class Topic {
}
}
public
static
boolean
isPublished
(
@TopicID
int
...
topics
)
{
for
(
int
topic
:
topics
)
{
if
(
topicList
[
topic
]
==
null
)
return
false
;
if
(!
topicList
[
topic
].
published
)
return
false
;
}
return
true
;
}
private
static
class
Store
{
boolean
published
=
false
;
Set
<
Subscriber
>
subscribers
=
new
HashSet
<>();
...
...
app/src/full/java/com/topjohnwu/magisk/utils/Utils.java
View file @
9ac71ff8
...
...
@@ -7,15 +7,20 @@ import android.content.Context;
import
android.content.SharedPreferences
;
import
android.database.Cursor
;
import
android.net.Uri
;
import
android.os.AsyncTask
;
import
android.provider.OpenableColumns
;
import
android.widget.Toast
;
import
com.topjohnwu.magisk.Const
;
import
com.topjohnwu.magisk.Data
;
import
com.topjohnwu.magisk.MagiskManager
;
import
com.topjohnwu.magisk.container.Module
;
import
com.topjohnwu.magisk.container.ValueSortedMap
;
import
com.topjohnwu.magisk.services.UpdateCheckService
;
import
com.topjohnwu.superuser.io.SuFile
;
import
java.util.Locale
;
import
java.util.Map
;
public
class
Utils
{
...
...
@@ -90,4 +95,19 @@ public class Utils {
public
static
void
toast
(
int
resId
,
int
duration
)
{
Data
.
mainHandler
.
post
(()
->
Toast
.
makeText
(
Data
.
MM
(),
resId
,
duration
).
show
());
}
public
static
void
loadModules
()
{
Topic
.
reset
(
Topic
.
MODULE_LOAD_DONE
);
AsyncTask
.
THREAD_POOL_EXECUTOR
.
execute
(()
->
{
Map
<
String
,
Module
>
moduleMap
=
new
ValueSortedMap
<>();
SuFile
path
=
new
SuFile
(
Const
.
MAGISK_PATH
);
String
[]
modules
=
path
.
list
(
(
file
,
name
)
->
!
name
.
equals
(
"lost+found"
)
&&
!
name
.
equals
(
".core"
));
for
(
String
name
:
modules
)
{
Module
module
=
new
Module
(
Const
.
MAGISK_PATH
+
"/"
+
name
);
moduleMap
.
put
(
module
.
getId
(),
module
);
}
Topic
.
publish
(
Topic
.
MODULE_LOAD_DONE
,
moduleMap
);
});
}
}
\ No newline at end of file
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