【问题标题】:Android 5.0/Lollipop: Force rescan of /system/priv-appAndroid 5.0/Lollipop:强制重新扫描 /system/priv-app
【发布时间】:2014-10-21 13:19:37
【问题描述】:

在 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!)

-> APK 未加载且未在 app-list 中列出 -> 与预期不同,APK 将在 Android 4.4 上的 priv-app 文件夹中自动安装。

2。重启设备,在 /system/priv-app 中有 APK

reboot

I/PackageManager(  567): /system/priv-app/AARSCService.apk changed; collecting certs

-> APK 已加载并在 app-list 中列出 -> 符合预期

3。将 APK 从 /system/priv-app 移动到 /system(=deinstallation)

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!)

-> APK 仍然加载并列在应用列表中,应用内的服务仍然可以从另一个应用绑定 -> 不像预期的那样,APK 将在 Android 4.4 上从 priv-app 文件夹中删除后自动卸载。

4。重启设备,APK 不在 /system/priv-app 中

reboot 

W/PackageManager(  570): System package eu.airaudio.aarscservice no longer exists; wiping its data

-> APK 不再加载,也不再列在 app-list 中 -> 符合预期

编辑 2:

在无根的 Android L (21) 模拟器上存在相同的行为 - 当然,没有 SELinux 警告。 但是 APK 也只是(卸载)在重启后安装(=kill zygote)。

【问题讨论】:

  • 只是一个观察,也许它有帮助:观察priv-app文件夹的代码没有从KK更改为L
  • 嗨,菲利普,是的,没错,这让我更加困惑。但是我已经认识到,只需将提供服务的 APK 放置/删除到“/system/priv-app”目录中,就不会再安装/卸载它了。但 APK 会在设备重启后安装。它不仅影响我当前的应用程序,而且影响我的竞争对手曾经在理论上做同样的事情。神秘 - 我会在接下来的几天里尝试在 PackageManagerService 上附加调试器。
  • @MartinM。你能添加来自PackageManagerService的日志消息吗?
  • 嘿 ashoke,我添加了一个完整的添加和删除 APK 的工作流程,感谢您的支持 :)

标签: android android-5.0-lollipop


【解决方案1】:

比较 KitKat 和 Lollipop 的 PackageManagerService 的源代码,您可以看到显着的变化,其中一些明显与这种变化有关。

PackageManagerService.java on Lollipop

PackageManagerService.java on KitKat

问题主题最显着的变化是删除了对 AppDirObserverPackageManagerService 的嵌套类)的所有引用,该引用被初始化为监视所有目录(附图显示了相关代码的比较已使用。右侧显示 KitKat 代码,左侧显示 Lollipop)

仍然没有找到解决方案,但可能会帮助某人解决这个问题。

【讨论】:

  • 你说得对 Muzikant,7 月 23 日的提交引入了这个“问题”:github.com/android/platform_frameworks_base/commit/… 我总是检查预览 #2 的来源(我希望),并且那些观察者仍然可用。希望有人可以找到解决此问题的方法。 1000 谢谢!
  • 查看该提交评论,它提到了“集群式”安装,它指的是应用程序现在如何放置在“system/app-priv”文件夹中(每个应用程序都有一个包含 APK 和艺术文件)。我想如果你能找到它的构建位置,你就会为你的问题找到解决方案。
  • 嘿 Muzikant,是的,我已经阅读过这种新的集群样式。我会接受不再自动安装动态移动的应用程序,并将要求我的用户重新启动他们的设备以触发安装。您的回答不是关于“如何触发”的问题,而是您回答了“为什么它不再起作用” - 我会检查如何用一些学分来兑现它:)
【解决方案2】:

根据您的 logcat 消息,PackageManagerService 似乎甚至没有看到文件夹/文件的更改。

这是规避/触发重新扫描的一种方法,通过广播操作模拟“启动完成”事件:

    adb shell am broadcast -a android.intent.action.BOOT_COMPLETED

这应该会触发PackageManagerService 的重新扫描

【讨论】:

  • 我还没有在 PackageManagerService 中找到该事件的监听器,但是谁知道呢。我将在今天晚些时候尝试这个,并希望它会起作用。您将获得成功的奖励 - 再次感谢您对此进行调查!
  • 遗憾的是,这个提示会使整个系统崩溃,导致软重启。有趣的是,系统现在似乎认识到 APK 发生了变化,例如。如果我删除它,它会开始发送 PACKAGE_REMOVED、PACKAGE_ADDED 事件,但它似乎很困难。要么这真的是最新的开发者预览中的一个错误,要么......还有什么进一步的想法?我认为我们走在正确的道路上。
  • @MartinM。你可以try other standard broadcast actions,可能是ACTION_PACKAGE_CHANGED 可能有帮助。
  • 遗憾的是,似乎没有触发任何重新扫描,而只是默认日志,例如“bla bla package xy changed”。即使通过 mv 重命名 priv-app 文件夹然后重命名它,也不会触发日志中的任何事件。我认为并希望这是最新预览中的一个错误..在系统软崩溃后重新扫描正在工作,这是理论上它应该工作的一个指标:(
  • @MartinM。看起来像文件/目录触发器events can be either move or close_write。可能是cdpriv-app 文件夹,并尝试touch tmp.txt;echo "0" >> tmp.txt,看看是否触发至少CLOSE_WRITE(因为MOVED_TO 事件似乎不起作用)。
【解决方案3】:

pms 将在开始时扫描/system/app(priv-app)。所以只需杀死进程systemserver :) 它在我的棒棒糖模拟器上工作。只需稍等片刻即可显示“升级 android,选择应用程序...”

【讨论】:

  • 嗨,Bowdom,感谢您的回答。这在理论上是完全正确的,但不是一种用户友好的方式。我更喜欢请用户手动重启并让他通过“重启”命令手动重启他的设备:)
【解决方案4】:
  1. 将 apk 推送到 /system/priv-app/
  2. 运行命令:adb shell > su > am restart(使用此命令不会丢失 adb 连接)
  3. 等待系统启动 - 安装脚本可以等待命令的干净输出:“adb shell dumpsys phone”

片段:

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

【讨论】:

  • 您好 Zelman,感谢您的帖子。由于重新启动是强制性的,我可以简单地要求用户重新启动并让他通过“立即重新启动”按钮重新启动。但是您的脚本是一个不错的插件,也许其他人可以集成它:)
【解决方案5】:

我遇到了完全相同的问题。 原来,当我将包处理回 priv-app 时,它是用不同的权限复制的

priv-app(和应用)中所有包的权限:

rwx-r-x-r-x

我复制回来的包的权限:

rwx--------

一个简单的chmod -R a+rw <path/to/package>就解决了问题

编辑: 通过发出确保您的 /system/ 不是只读的 mount -o remount,rw /system/

【讨论】:

  • 这对我不起作用。该软件包仍未自动安装。也许我在这里遗漏了一些东西。你能发布你完整的shell命令吗?
  • 这就是完整的shell命令。只需将 替换为包的路径,例如 chmod -R 755 /system/apps/Bluetooth/ 在此之前确保 /system 目录不是只读 mount -orw,remount /system
  • 我指的是用于将 apk 安装到系统分区的完整 shell 命令。显然,您需要以某种方式将其移动到系统分区。正如本线程中所讨论的,它适用于 Pre-Lollipop,但不适用于 Lollipop。我的 shell 命令在这里:gitlab.com/fdroid/fdroidclient/commit/… 在 Lollipop 上,需要重新启动才能重新扫描 priv-app 目录以查找新移动的 apk。
  • adb push [-p] 。只需在您的手机中选择您可以写入的任何临时目录(可能是 /mnt/extSdCard/ )并将您的包推到那里然后从 adb shell 内部执行“mv /mnt/extSdCard/mypackage /system/priv-app” 希望帮助
【解决方案6】:

给你:

adb shell cmd package compile -f -r first-boot com.yourpackage.name

【讨论】:

    猜你喜欢
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-02
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多