今天在安装 APP 进行调试的时候,发现一直安装不上,显示: Too many active sessions for UID xxx,一开始还以为是调试的 APP 的问题,但是试了其他 APP 也不行。

从往上搜索了很多的方法都不行,估计都是复制粘贴的答案,不得已只能自己去源码中寻找答案。

于是在源码中进行搜索:https://cs.android.com/

于是定位到了: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java;l=805;drc=f753975e2f324789b33253d728870d8eb29f7214

里面的 createSessionInternal 方法:

synchronized (mSessions) {
   // Check that the installer does not have too many active sessions.
   final int activeCount = getSessionCount(mSessions, callingUid);
   if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)
           == PackageManager.PERMISSION_GRANTED) {
       if (activeCount >= MAX_ACTIVE_SESSIONS_WITH_PERMISSION) {
           throw new IllegalStateException(
                   "Too many active sessions for UID " + callingUid);
       }
   } else if (activeCount >= MAX_ACTIVE_SESSIONS_NO_PERMISSION) {
       throw new IllegalStateException(
               "Too many active sessions for UID " + callingUid);
   }
   final int historicalCount = mHistoricalSessionsByInstaller.get(callingUid);
   if (historicalCount >= MAX_HISTORICAL_SESSIONS) {
       throw new IllegalStateException(
               "Too many historical sessions for UID " + callingUid);
   }

   sessionId = allocateSessionIdLocked();
}

然后就看了 activeCount 获取方法 getSessionCount,里面主要根据 uid 去查询 mSessions 中有多少该 uid 中的 session,那 mSessions 又是来自哪里?

此时我们就会找到 readSessionsLocked 方法,查看 mSessions 赋值的过程

private void readSessionsLocked() {
    if (LOGD) Slog.v(TAG, "readSessionsLocked()");

    mSessions.clear();

    FileInputStream fis = null;
    try {
        fis = mSessionsFile.openRead();
        final TypedXmlPullParser in = Xml.resolvePullParser(fis);

        int type;
        while ((type = in.next()) != END_DOCUMENT) {
            if (type == START_TAG) {
                final String tag = in.getName();
                if (PackageInstallerSession.TAG_SESSION.equals(tag)) {
                    final PackageInstallerSession session;
                    try {
                        session = PackageInstallerSession.readFromXml(in, mInternalCallback,
                                mContext, mPm, mInstallThread.getLooper(), mStagingManager,
                                mSessionsDir, this, mSilentUpdatePolicy);
                    } catch (Exception e) {
                        Slog.e(TAG, "Could not read session", e);
                        continue;
                    }
                    mSessions.put(session.sessionId, session);
                    mAllocatedSessions.put(session.sessionId, true);
                }
            }
        }
    } catch (FileNotFoundException e) {
        // Missing sessions are okay, probably first boot
    } catch (IOException | XmlPullParserException e) {
        Slog.wtf(TAG, "Failed reading install sessions", e);
    } finally {
        IoUtils.closeQuietly(fis);
    }
    // After reboot housekeeping.
    for (int i = 0; i < mSessions.size(); ++i) {
        PackageInstallerSession session = mSessions.valueAt(i);
        session.onAfterSessionRead(mSessions);
    }
}

然后终于发现是从 mSessionsFile 这个文件中读取出来的,那这个路径在哪?我们去找找赋值的地方。

mSessionsFile = new AtomicFile(
                new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
                "package-session");

一切都明了了,是从 /data/system/install_sessions.xml 文件中读取的,那就好办了,我们直接删除这个文件重启就行了。