Android 5.0/Lollipop: принудительное повторное сканирование /system/priv-app
В Android 4.x было достаточно поместить APK-файл в /system/priv-app, и менеджер пакетов распознал этот новый файл и (не) установил соответствующее приложение или службу.
Начиная с Android L, кажется, недостаточно просто поместить файл в этот каталог - требуется перезагрузка системы, чтобы заставить Android распознать это изменение.
Кто-нибудь знает, как это обойти? Может быть с любым setprop ctl.restart xxx
или убивая выделенный сервис?
РЕДАКТИРОВАТЬ:
Вот некоторые журналы от logcat:
1. Переместите APK из / system в /system/priv-app (= установка)
su
mount -o remount rw /system
cd /system/priv-app
mv ../AARSCService.apk . // move from /system to /system/priv-app
W/mv ( 3268): type=1400 audit(0.0:53): avc: denied { rename } for name="AARSCService.apk" dev="mmcblk0p22" ino=23041 scontext=u:r:init:s0 tcontext=u:object_r:system_file:s0 tclass=file
(но файл был перемещен, поскольку текущая корневая реализация для Nexus 7 Android Android L P2 отключает SELinux для команд root!)
-> APK НЕ загружен и не указан в списке приложений -> НЕ как ожидалось, APK будет автоматически установлен после помещения в папку priv-app на Android 4.4.
2. Перезагрузите устройство, имея APK внутри / system / priv-app
reboot
I/PackageManager( 567): /system/priv-app/AARSCService.apk changed; collecting certs
-> APK загружен и указан в списке приложений -> как и ожидалось
3. Переместите APK из / system / priv-app в /system (= удаление)
su
mount -o remount rw /system
cd /system/priv-app
mv AARSCService.apk .. // move from /system/priv-app to /system
W/mv ( 3189): type=1400 audit(0.0:31): avc: denied { rename } for name="AARSCService.apk" dev="mmcblk0p22" ino=23041 scontext=u:r:init:s0 tcontext=u:object_r:system_file:s0 tclass=file
(но файл был перемещен, поскольку текущая корневая реализация для Nexus 7 Android Android L P2 отключает SELinux для команд root!)
-> APK все еще загружен и находится в списке приложений, сервис внутри приложения все еще может быть связан с другим приложением -> НЕ как ожидалось, APK будет автоматически удален после удаления из папки priv-app на Android 4.4.
4. Перезагрузите устройство, имея APK НЕ внутри / system / priv-app
reboot
W/PackageManager( 570): System package eu.airaudio.aarscservice no longer exists; wiping its data
-> APK больше не загружается и не отображается в списке приложений -> как ожидалось
РЕДАКТИРОВАТЬ 2:
То же самое происходит в эмуляторе Android L (21) без рутирования - конечно, без SELinux-предупреждения. Но APK также просто (не) устанавливается после перезагрузки (=kill zygote).
5 ответов
Сравнение исходного кода PackageManagerService
между KitKat и Lollipop вы можете увидеть существенные изменения, а некоторые, очевидно, связаны с этим изменением.
PackageManagerService.java
на леденец
PackageManagerService.java
на КитКат
Наиболее значительным изменением в теме вопроса является удаление всех ссылок на AppDirObserver
(вложенный класс PackageManagerService
), который был инициализирован для мониторинга всех каталогов (на прилагаемом изображении показано сравнение соответствующего кода, в котором он использовался. На правой стороне показан код KitKat, а на левой стороне показан Lollipop)
До сих пор не нашел решения для этого, но может помочь кому-то понять это.
Исходя из ваших сообщений logcat, выглядит как PackageManagerService
даже не видит изменения папки / файла.
Вот один из способов обойти / запустить повторное сканирование, смоделировать событие "загрузка завершена" с помощью широковещательного действия:
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED
Это должно вызвать повторное сканирование PackageManagerService
ПМС будет сканировать /system/app(priv-app)
в начале. так что просто убей процесс systemserver
:) это работает на моем эмуляторе леденца на палочке. просто потратьте немного времени на показ "обновить Android, выбрать приложение..."
Ну вот:
adb shell cmd package compile -f -r first-boot com.yourpackage.name
- Нажмите apk для /system/priv-app/
- Запустите команду: adb shell > su > am restart (с помощью этой команды вы не потеряете соединение adb)
- Ожидание загрузки системы - установочный скрипт может ожидать чистого вывода команды: "adb shell dumpsys phone"
Snippet:
def am_restart(self):
"""Restarts am waits for complete Android boot."""
self._log.info('Restarting application manager!')
ret, out, err = self.shell('am restart', require_root=True)
if ret != 0:
self.log_failure('am restart', ret, out, err)
return False
on_main_screen = False
while not on_main_screen:
sleep(2)
ret, out, err = self.shell('dumpsys phone')
if ret != 0:
self.log_failure('dumpsys phone', ret, out, err)
return False
if not (out or err):
on_main_screen = True
self._log.info('Application manager successfully restarted!')
return True
У меня была точно такая же проблема. Оказывается, когда я скопировал пакет обратно в priv-app, он был скопирован с другим разрешением
Разрешения всех пакетов в priv-app (и app):
rwx-r-x-r-x
Разрешение на пакет я скопировал обратно:
rwx--------
Просто chmod -R a+rw <path/to/package>
решил проблему
РЕДАКТИРОВАТЬ: убедитесь, что ваш /system/ не только для чтения, выдав mount -o remount,rw /system/