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
  1. Нажмите apk для /system/priv-app/
  2. Запустите команду: adb shell > su > am restart (с помощью этой команды вы не потеряете соединение adb)
  3. Ожидание загрузки системы - установочный скрипт может ожидать чистого вывода команды: "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/

Другие вопросы по тегам