This repository has been archived by the owner on Oct 29, 2022. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy path000gappsintegrator
executable file
·478 lines (402 loc) · 18.2 KB
/
000gappsintegrator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
#!/system/bin/sh
# chmod -R 755 /system/etc/init.d /system/su.d /su/su.d /sbin/supersu/su.d /magisk/.core/post-fs-data.d /sbin/.core/img/.core/post-fs-data.d /data/adb/post-fs-data.d
#
# ROM GApps Auto-Integration
# osm0sis @ xda-developers
debugging=0
dryrun=0
logbuff() { logbuff+="$($*)"; }
writable() { touch $1/tmpfile 2>/dev/null; ret=$?; rm $1/tmpfile 2>/dev/null; echo $ret; }
# figure out if the next integration will likely have enough free space in /system
freespace-estimate() {
free=$(df -Ph /system 2>>$out | tail -n 1 | awk '{ print $4 }');
case $free in *K) free=0;; *M) free=`echo $free | cut -dM -f1 | cut -d. -f1`;; *G) free=$((`echo $free | cut -dG -f1 | cut -d. -f1` * 1024));; esac;
libsize=0; buffer=4;
if [ "$nozipbins" ]; then
for entry in $(unzip -l $1 lib/* 2>>$out | tail -n +4 | awk '{ print $1 }'); do
case $entry in
---------) ;; # skip top line displayed in some unzip list edge cases
--------) break;;
*) libsize=$((libsize + entry));;
esac;
done;
if [ $libsize -lt 1048576 ]; then
libsize=1;
else
libsize=$((libsize / 1048576));
fi;
else
buffer=8;
fi;
datapksize=$(du -m $1 | awk '{ print $1 }');
sysapksize=$(du -m $2 | awk '{ print $1 }');
need=$((datapksize + libsize - sysapksize + buffer));
echo "free($free) ?> need($need) = datapksize($datapksize) + libsize($libsize) - sysapksize($sysapksize) + buffer($buffer)" >> $out;
[ $free -gt $need ]; echo $?;
}
# determine if final replacement APK and library sizes will fit in /system
freespace-precise() {
free=$(df -Ph /system 2>>$out | tail -n 1 | awk '{ print $4 }');
case $free in *K) free=0;; *M) free=`echo $free | cut -dM -f1 | cut -d. -f1`;; *G) free=$((`echo $free | cut -dG -f1 | cut -d. -f1` * 1024));; esac;
oldfiles=$(du -mc $1 2>>$out | tail -n1 | awk '{ print $1 }');
newfiles=$(du -mc $2 2>>$out | tail -n1 | awk '{ print $1 }');
echo "free($free) + oldfiles($oldfiles) = total_space($((free + oldfiles))) ?> newfiles($newfiles)" >> $out;
[ $((free + oldfiles)) -gt $newfiles ]; echo $?;
}
# add support for Magisk by altering the actual mounted system partition
[ -d /magisk/.core/mirror ] && magisk=/magisk/.core/mirror;
[ -d /sbin/.core/mirror ] && magisk=/sbin/.core/mirror;
[ -d /sbin/.magisk/mirror ] && magisk=/sbin/.magisk/mirror;
[ -e /dev/*/.magisk/mirror ] && magisk=$(echo /dev/*/.magisk/mirror);
# alter Magisk's post-fs-data.d PATH to prioritize actual mounted system over the included busybox
[ "$magisk" ] && export PATH="$magisk/system/bin:$magisk/system/xbin:$PATH";
# group all commands and allow redirection of output for debugging
out=/dev/null;
[ "$debugging" == 1 ] && out=/data/local/tmp/debug-gappsint.log;
(
# run in an asynchronous subshell to not impede the boot with su.d/post-fs-data.d
{
# loop counter timeout limits for device writability
sdlimit=900; syslimit=120;
# define working paths
gtmp=/data/local/tmp/gapp;
gbak=/data/local/tmp/gxml-bak;
log=/sdcard/gapps-integrator.log;
# create log/change filedate immediately to indicate script is active once /sdcard is available
counter1=0;
until [ "$(writable /sdcard; touch $log 2>/dev/null)" == 0 -o "$counter1" -gt "$sdlimit" ]; do
sleep 1;
counter1=$((counter1 + 1));
done&
if [ "$dryrun" == 0 ]; then
# wait for /system to become remountable/writable, abort if it does not
counter2=0;
until [ "$(mount --help 2>/dev/null)" ] && [ "$(mount -o rw,remount -t auto $magisk/system >>$out; writable $magisk/system; mount -o ro,remount -t auto $magisk/system >>$out)" == 0 -o "$counter2" -gt "$syslimit" ]; do
sleep 1;
counter2=$((counter2 + 1));
done;
if [ "$counter2" -gt "$syslimit" ]; then
logbuff echo -ne "\n\x20* Fatal error: $magisk/system did not become remountable/writable during boot\n\n";
abort=1;
fi;
fi;
# log earliest accurate processing start timestamp once date stops returning epoch in early boot
until [ "$(date 2>/dev/null)" ] && [ ! "$(date | grep '1970')" ] && [ ! "$(date | grep '1999')" ] && [ ! "$(date | grep '2000')" ]; do
sleep 1;
done;
logbuff echo -n `date`;
echo -ne "\n$(date) ";
if [ "$dryrun" == 1 ]; then
logbuff echo -ne "\n\x20* Dry run mode: No actual changes will be made to $magisk/system or /data";
echo -ne "--- Dry run mode! ";
fi;
# test for and try to ensure a working basic script environment, often broken in Marshmallow (AOSP)
for i in awk basename cut dirname sed tail unzip which; do
if [ ! "$(which $i)" ]; then
logbuff echo -ne "\n\x20* Missing script environment element detected: $i";
abort=1;
fi;
done;
if [ ! "$(echo testing | sed 's/test/pass/')" == "passing" ]; then
logbuff echo -ne "\n\x20* Broken script environment element detected: sed";
if [ "$(echo testing | busybox sed 's/test/pass/')" == "passing" ]; then
logbuff echo -ne "\n\x20* -- using busybox sed instead";
bb=busybox;
else
abort=1;
fi;
fi;
touch /data/local/testfile1; touch /data/local/testfile2;
if [ ! "$(chmod 666 /data/local/testfile*; echo $?)" == 0 ]; then
logbuff echo -ne "\n\x20* Broken script environment element detected: chmod";
if [ "$(busybox chmod 666 /data/local/testfile*; echo $?)" == 0 ]; then
logbuff echo -ne "\n\x20* -- using busybox chmod instead";
bb=busybox;
else
abort=1;
fi;
fi;
rm -f /data/local/testfile*;
# check for zip and zipalign binaries to determine integration method
for i in zip zipalign; do
if [ ! "$(which $i)" ]; then
logbuff echo -ne "\n\x20* Missing binary for primary integration method: $i";
nozipbins=1;
fi;
done;
[ "$nozipbins" ] && logbuff echo -ne "\n\x20* -- using fallback method instead";
# get SDK version to perform different actions due to /data/app layout changes
sdkver=`getprop ro.build.version.sdk`;
[ ! "$sdkver" ] && sdkver=$(grep '^ro.build.version.sdk' $magisk/system/build.prop | cut -d= -f2);
# find new unintegrated Google Apps APKs in /data
for i in $(ls /data/app/ | grep -E '^com.android|^com.chrome|^com.google.android|^com.google.earth|^com.motorola'); do
# skip all if script environment is broken
[ "$abort" ] && break;
# find equivalent /system APK name and only process if it exists
xml=/data/system/packages.xml;
package=`echo $i | rev | cut -d- -f2- | rev`;
sysapk=$(grep "updated-package name=\"$package\"" $xml | grep -o 'codePath=.*$' | cut -d\" -f2);
logbuff echo -ne "\n/data/app/$i $sysapk";
if [ "$sysapk" ]; then
# compare /data and /system APK versions and only integrate if /data is newer (necessary on Lollipop and above)
datver=$(grep "codePath=\"/data/app/$i\"" $xml | grep -o 'version=.*$' | cut -d\" -f2);
sysver=$(grep "codePath=\"$sysapk\"" $xml | grep -o 'version=.*$' | cut -d\" -f2);
if [ "$datver" -gt "$sysver" ]; then
logbuff echo -ne "\x20($datver > $sysver)";
echo -e "\n$i $magisk$sysapk";
rm -rf $gtmp;
mkdir -p $gtmp;
# KitKat (and below) support
if [ "$sdkver" -le 20 ]; then
datapk=/data/app/$i;
# exclude APKs that cause breakage after integration
case $package in
com.google.android.apps.messaging|com.google.android.apps.photos|com.google.android.apps.plus|com.google.android.street|com.google.android.talk|com.google.android.youtube)
logbuff echo -ne "\x20!";
continue;;
esac;
# skip current APK if it fails a free space check
if [ "$(freespace-estimate $datapk $magisk$sysapk)" != 0 ]; then
logbuff echo -ne "\x20*";
continue;
fi;
# remove libraries from copied APK and zipalign if the binaries exist
if [ ! "$nozipbins" ]; then
cp -fp $datapk $gtmp/preopt-$i;
zip -d $gtmp/preopt-$i lib/*/*;
zipalign 4 $gtmp/preopt-$i $gtmp/$i;
datapk=$gtmp/$i;
fi;
# extract and force copy libraries to /system, abort if fails final total space check
unzip /data/app/$i -d $gtmp lib/*;
for j in $(ls $gtmp/lib/*/); do
liblist="$liblist $magisk/system/lib/$j";
done;
if [ "$(freespace-precise "$magisk$sysapk $liblist" "$datapk $gtmp/lib/*/*" )" != 0 ]; then
logbuff echo -ne "\x20**";
continue;
fi;
$bb chmod 644 $gtmp/lib/*/*;
if [ "$dryrun" == 0 ]; then
mount -o rw,remount -t auto $magisk/system;
rm -f $magisk$sysapk;
cp -fp $gtmp/lib/*/* $magisk/system/lib/;
# overwrite /system APK with new /data APK then fix permissions
cp -f $datapk $magisk$sysapk;
chown root.root $magisk$sysapk;
$bb chmod 644 $magisk$sysapk;
fi;
# Lollipop support
elif [ "$sdkver" -le 22 ]; then
datapk=/data/app/$i/base.apk;
sysname=`basename $sysapk`;
# save time on boots after APK work has been completed but apps are awaiting optimization
if [ ! -f /data/app/$i/integrated ]; then
# skip current APK if it fails a free space check
if [ "$(freespace-estimate $datapk $magisk$sysapk/$sysname.apk)" != 0 ]; then
logbuff echo -ne "\x20*";
continue;
fi;
# remove libraries from copied APK and zipalign if the binaries exist
if [ ! "$nozipbins" ]; then
# workaround for Chrome not playing by the usual rules (per usual)
case $package in
com.android.chrome|com.chrome.*)
if [ "$dryrun" == 0 ]; then
mount -o rw,remount -t auto $magisk/system;
rm -f $magisk$sysapk/lib/*/libchrome.so;
fi;;
*)
cp -fp $datapk $gtmp/preopt-$i.apk;
zip -d $gtmp/preopt-$i.apk lib/*/*;
zipalign 4 $gtmp/preopt-$i.apk $gtmp/$i.apk;
datapk=$gtmp/$i.apk;;
esac;
fi; # end nozipbins test
# abort if fails final total space check
if [ "$(freespace-precise "$magisk$sysapk" "$datapk /data/app/$i/lib" )" != 0 ]; then
logbuff echo -ne "\x20**";
continue;
fi;
if [ "$dryrun" == 0 ]; then
# force copy libraries to /system respecting symlinks then clean up empty files
mount -o rw,remount -t auto $magisk/system;
rm -f $magisk$sysapk/$sysname.apk;
cp -RLf /data/app/$i/lib $magisk$sysapk;
for j in `ls $magisk$sysapk/lib/*/*`; do
[ ! -s $j ] && rm -f $j;
done;
# overwrite /system APK with new /data APK then fix permissions
cp -fp $datapk $magisk$sysapk/$sysname.apk;
chown -R root.root $magisk$sysapk;
$bb chmod -R 755 $magisk$sysapk/lib;
$bb chmod 644 $magisk$sysapk/$sysname.apk $magisk$sysapk/lib/*/*;
# flag for cleanup on reboot following optimization
touch /data/app/$i/integrated;
fi;
fi; # end integrated test
if [ "$dryrun" == 0 ]; then
# remove packages.xml entry for /data APK and ensure proper ownership/permissions
md5sum $xml;
if [ "$(grep "<updated-package name=\"${package}\"" $xml | grep '/>')" ]; then
$bb sed -i "/<updated-package name=\"${package}\"/d" $xml;
else
$bb sed -i "/<updated-package name=\"${package}\"/,/<\/updated-package>/d" $xml;
fi;
chown system:system $xml;
$bb chmod 660 $xml;
md5sum $xml;
fi;
# Marshmallow (and above) support
elif [ "$sdkver" -ge 23 ]; then
datapk=/data/app/$i/base.apk;
sysname=`basename $sysapk`;
# save time on boots after APK work has been completed but apps are awaiting optimization
if [ ! -f /data/app/$i/integrated ]; then
# skip current APK if it fails a free space check
if [ "$(freespace-estimate $datapk $magisk$sysapk/$sysname.apk)" != 0 ]; then
logbuff echo -ne "\x20*";
continue;
fi;
# decompress libraries within copied APK and zipalign if the binaries exist (maintains proper Marshmallow and above structure)
if [ ! "$nozipbins" ]; then
unzip $datapk -d $gtmp lib/*;
cp -fp $datapk $gtmp/preopt-$i.apk;
zip -d $gtmp/preopt-$i.apk lib/*/*;
cd $gtmp;
zip -r -0 -D $gtmp/preopt-$i.apk lib/;
zipalign -p 4 $gtmp/preopt-$i.apk $gtmp/$i.apk;
datapk=$gtmp/$i.apk;
# abort if fails final total space check
datoat=/data/app/$i/oat;
[ -d $magisk$sysapk/oat ] || unset datoat;
if [ "$(freespace-precise "$magisk$sysapk/$sysname.apk $magisk$sysapk/oat $magisk$sysapk/lib" "$datapk $datoat" )" != 0 ]; then
logbuff echo -ne "\x20**";
continue;
fi;
if [ "$dryrun" == 0 ]; then
# remove any unpacked libraries in the /system APK directory since they are no longer needed
mount -o rw,remount -t auto $magisk/system;
[ -d $magisk$sysapk/lib ] && rm -rf $magisk$sysapk/lib;
fi;
else
# otherwise force copy libraries to /system respecting symlinks then clean up empty files, abort if fails final total space check
datoat=/data/app/$i/oat;
[ -d $magisk$sysapk/oat ] || unset datoat;
if [ "$(freespace-precise "$magisk$sysapk/$sysname.apk $magisk$sysapk/oat $magisk$sysapk/lib" "$datapk $datoat /data/app/$i/lib" )" != 0 ]; then
logbuff echo -ne "\x20**";
continue;
fi;
if [ -e /data/app/$i/lib/* -a "$dryrun" == 0 ]; then
mount -o rw,remount -t auto $magisk/system;
cp -RLf /data/app/$i/lib $magisk$sysapk;
for j in `ls $magisk$sysapk/lib/*/*`; do
[ ! -s $j ] && rm -f $j;
done;
fi;
fi; # end nozipbins test
if [ "$dryrun" == 0 ]; then
# if necessary force copy APK odex file to /system
mount -o rw,remount -t auto $magisk/system;
if [ -d $magisk$sysapk/oat ]; then
cp -fp /data/app/$i/oat $magisk$sysapk;
cd $magisk$sysapk/oat/*/;
mv base.odex $sysname.odex;
fi;
# overwrite /system APK with new /data APK then fix permissions
cp -fp $datapk $magisk$sysapk/$sysname.apk;
chown -R root.root $magisk$sysapk;
$bb chmod -R 755 $magisk$sysapk/lib $magisk$sysapk/oat;
$bb chmod 644 $magisk$sysapk/$sysname.apk $magisk$sysapk/lib/*/* $magisk$sysapk/oat/*/*;
# flag for cleanup on reboot following optimization
touch /data/app/$i/integrated;
fi;
fi; # end integrated test
if [ "$dryrun" == 0 ]; then
# remove packages.xml entry for /data APK and ensure proper ownership/permissions
md5sum $xml;
if [ "$(grep "<updated-package name=\"${package}\"" $xml | grep '/>')" ]; then
$bb sed -i "/<updated-package name=\"${package}\"/d" $xml;
else
$bb sed -i "/<updated-package name=\"${package}\"/,/<\/updated-package>/d" $xml;
fi;
chown system:system $xml;
$bb chmod 660 $xml;
md5sum $xml;
# workaround for APKs that cause breakage after integration by temporarily removing runtime-permissions.xml to force rebuild
case $package in
com.google.android.calendar|com.google.android.inputmethod.*|com.google.android.play.games|com.google.android.tts|com.google.android.webview)
logbuff echo -ne "\x20~";
if [ ! -d $gbak ]; then
mkdir -p $gbak;
for rtperm in /data/system/users/*/runtime-permissions.xml; do
if [ -e "$rtperm" ]; then
user=`basename $(dirname $rtperm)`;
cp -fp $rtperm $gbak/$user;
rm -f $rtperm;
fi;
done;
fi;;
esac;
fi;
fi; # end sdkver test
if [ "$dryrun" == 0 ]; then
mount -o ro,remount -t auto $magisk/system;
fi;
else
if [ "$dryrun" == 0 ]; then
# clean up any duplicate packages that are not the current active copy
rm -rf /data/app/$i;
fi;
fi; # end datver+sysver test
elif [ -f /data/app/$i/integrated ]; then
# clean up to mimic pre-Lollipop (AOSP) behavior
rm -rf /data/app/$package-*;
fi; # end sysapk test
done; # end find unintegrated loop
# global cleanups required on Lollipop (and above)
if [ "$sdkver" -ge 21 -a "$dryrun" == 0 ]; then
# fix /system/lib permissions to ensure libs copied via symlink are correct
mount -o rw,remount -t auto $magisk/system;
[ "$magisk" ] && mount -o rw,remount -t auto /system;
chown root.root $magisk/system/lib/*.so;
$bb chmod 644 $magisk/system/lib/*.so;
mount -o ro,remount -t auto $magisk/system;
[ "$magisk" ] && mount -o ro,remount -t auto /system;
fi;
rm -rf $gtmp;
# write buffered log once /sdcard is available, fallback to a known working location if this fails
counter3=0;
until [ "$(writable /sdcard)" == 0 -o "$counter3" -gt "$sdlimit" ]; do
sleep 1;
counter3=$((counter3 + 1));
done;
[ "$counter3" -gt "$sdlimit" ] && log=/data/local/gapps-integrator.log;
[ ! -s $log ] && echo -e "## GApps Auto-Integration Script Log\n#\n# ~ = forced permissions list rebuild,\n# * = not enough free space, ! = excluded\n" > $log;
echo "$logbuff" >> $log;
echo "---" >> $log;
# limit log length to ~16Kb (when exceeded) by removing oldest entry
[ "$(du -k $log | cut -f1)" -gt 16 ] && $bb sed -i "/$(grep -m1 -vE '^$|^#.*$' $log)/,/^\s*$/d" $log;
# restore runtime-permissions.xml backup files to maintain granted user app permissions and reboot after boot is completed
counter4=0;
if [ -d "$gbak" -a "$dryrun" == 0 ]; then
until [ "$(getprop sys.boot_completed)" == 1 -o "$counter4" -gt "$sdlimit" ]; do
sleep 1;
counter4=$((counter4 + 1));
done;
if [ "$counter4" -gt "$sdlimit" ]; then
echo "Ooops! Timeout for boot completion to restore user app runtime-permissions files" >> $log;
echo "---" >> $log;
fi;
for user in `ls $gbak`; do
cp -fp $gbak/$user /data/system/users/$user/runtime-permissions.xml;
done;
rm -rf $gbak;
echo "Rebooting after restoring user app runtime-permissions files" >> $log;
echo -e "---\n" >> $log;
reboot;
fi;
echo -ne "\n" >> $log;
echo "---";
}&
) >> $out 2>&1;