{"record":{"id":"89402a4b25e270a7","repo":"asLody/VirtualApp","slug":"caller-has-no-access-to-session","errorCode":null,"errorMessage":"Caller has no access to session ","messagePattern":"Caller has no access to session ","errorType":"exception","errorClass":"java.lang.SecurityException","httpStatus":null,"severity":"error","filePath":"VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/installer/VPackageInstallerService.java","lineNumber":129,"sourceCode":"            // Sanity check that installer isn't going crazy\n            final int activeCount = getSessionCount(mSessions, callingUid);\n            if (activeCount >= MAX_ACTIVE_SESSIONS) {\n                throw new IllegalStateException(\n                        \"Too many active sessions for UID \" + callingUid);\n            }\n            sessionId = allocateSessionIdLocked();\n            session = new PackageInstallerSession(mInternalCallback, mContext, mInstallHandler.getLooper(), installerPackageName, sessionId, userId, callingUid, params, VEnvironment.getPackageInstallerStageDir());\n        }\n        mCallbacks.notifySessionCreated(session.sessionId, session.userId);\n        return sessionId;\n    }\n\n    @Override\n    public void updateSessionAppIcon(int sessionId, Bitmap appIcon) {\n        synchronized (mSessions) {\n            final PackageInstallerSession session = mSessions.get(sessionId);\n            if (session == null || !isCallingUidOwner(session)) {\n                throw new SecurityException(\"Caller has no access to session \" + sessionId);\n            }\n\n            session.params.appIcon = appIcon;\n            session.params.appIconLastModified = -1;\n\n            mInternalCallback.onSessionBadgingChanged(session);\n        }\n    }\n\n    @Override\n    public void updateSessionAppLabel(int sessionId, String appLabel) throws RemoteException {\n        synchronized (mSessions) {\n            final PackageInstallerSession session = mSessions.get(sessionId);\n            if (session == null || !isCallingUidOwner(session)) {\n                throw new SecurityException(\"Caller has no access to session \" + sessionId);\n            }\n            session.params.appLabel = appLabel;\n            mInternalCallback.onSessionBadgingChanged(session);","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/asLody/VirtualApp/blob/666fefcb5d3f39cc944001c3457c38ffd6544c87/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/installer/VPackageInstallerService.java#L111-L147","documentation":"Session handles in VPackageInstallerService are owner-scoped: updateSessionAppIcon looks up the session and requires that the caller's UID equals the session's creator UID (isCallingUidOwner). If the session doesn't exist or the caller isn't its owner, it throws SecurityException('Caller has no access to session ' + sessionId).","triggerScenarios":"Calling updateSessionAppIcon(sessionId, icon) with an expired/invalid sessionId, or from a different UID/process than the one that created the session.","commonSituations":"Two app processes (or an app and a service) sharing session IDs; session already finished/abandoned and its ID recycled or removed; using a hardcoded sessionId copied from another app's flow; VirtualApp multi-user setups calling across user/UID boundaries.","solutions":["Verify the sessionId came from createSession in the same process/UID and is still active.","Set the app icon in the SessionParams before createSession instead of mutating afterwards.","Handle the SecurityException by re-creating the session rather than retrying with the same ID.","If cross-process control is needed, route the call through the owning process."],"exampleFix":"// before\ninstaller.updateSessionAppIcon(42, icon); // SecurityException if not owner/session gone\n\n// after\nSessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);\nparams.setAppIcon(icon);\nint sessionId = installer.createSession(params); // icon set at creation, owned by this UID","handlingStrategy":"try-catch","validationCode":"// Only touch sessionIds returned by createSession in this process\nif (!ownedSessions.contains(sessionId)) {\n    throw new SecurityException(\"Not the owner of session \" + sessionId);\n}","typeGuard":"boolean ownsSession(Set<Integer> owned, int sessionId) { return owned.contains(sessionId); }","tryCatchPattern":"try {\n    installer.updateSessionAppIcon(sessionId, icon);\n} catch (SecurityException e) {\n    if (String.valueOf(e.getMessage()).startsWith(\"Caller has no access to session\")) {\n        // recreate the session with icon set in params\n    } else throw e;\n}","preventionTips":["Set appIcon via SessionParams at creation time instead of updating later.","Never hardcode or share sessionIds across processes.","Treat finished/abandoned sessions as inaccessible; re-create when needed."],"tags":["security-exception","ownership","session-not-found","android"],"backgroundTag":"permission-denied","analyzedSha":"666fefcb5d3f39cc944001c3457c38ffd6544c87","analyzedAt":"2026-09-09T11:09:01.694Z","contentChangedAt":"2026-09-09T11:09:01.694Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}