asLody/VirtualApp · error · SecurityException
Who are you?
Error message
Who are you?
What it means
acquireProviderClient() resolves the calling process via VActivityManagerService's mPidsSelfLocked map. If findProcessLocked(getCallingPid()) returns null, the caller is not a process VirtualApp spawned or recorded, and it throws SecurityException("Who are you?") to reject untrusted/unregistered callers.
Solutions
- Ensure the caller process is started through VirtualApp's VActivityManager/StubActivity path so its ProcessRecord is registered in mPidsSelfLocked.
- Retry after the process has fully initialized; if the process was killed, restart it via the virtual framework before accessing providers.
- Verify provider access goes through the in-app ContentResolver (virtualized), not a raw cross-app binder call from an unmanaged process.
- Check for races: acquire the provider after ActivityThread/daemon installProvider startup completes, or add the caller record earlier in process setup.
Example fix
// before (raw call from an unregistered process) IBinder client = vAms.acquireProviderClient(userId, providerInfo); // after (go through the virtualized resolver in the managed process) ContentResolver resolver = getContext().getContentResolver(); Cursor c = resolver.query(VirtualAppProvider.uriFor(userId, providerInfo), ...);
Defensive patterns
Strategy: retry
Validate before calling
ProcessRecord rec = VActivityManagerService.get().findProcessLocked(android.os.Process.myPid());
if (rec == null) {
throw new IllegalStateException("Process not registered with VirtualApp; cannot acquire provider client");
} Try / catch
try {
IBinder client = vAms.acquireProviderClient(userId, providerInfo);
} catch (SecurityException e) {
if ("Who are you?".equals(e.getMessage())) {
// caller not registered: re-attach/restart the process via VirtualApp then retry once
vAms.startProcessIfNeedLocked(processName, userId, packageName);
} else {
throw e;
}
} Prevention
- Only access virtual providers from processes launched through VirtualApp's StubActivity/daemon path.
- Avoid direct binder calls to VActivityManagerService from unmanaged or external apps.
- Handle process-death/restart flows so the ProcessRecord is re-registered before provider access.
- Watch startup ordering: acquire providers only after the virtual process table is populated.
When it happens
Trigger: A process whose PID is not in VActivityManagerService's process table requests a provider client: the call is made from a process not launched through VirtualApp (e.g. an outside app binding the service directly), the ProcessRecord was removed (process killed/restarted) before acquireProviderClient ran, or the provider request races with process startup.
Common situations: ContentProvider access from a newly forked app process before VActivityManager registered it; multi-process apps where a secondary process was started natively (not via VirtualApp); timing issues after the virtual process was killed by the system and re-attached without re-registering.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Unable to create application
- Invalid userId
- You need MANAGE_USERS permission to:
- Failed to allocate session ID
- Invalid userId
AI-assisted analysis of asLody/VirtualApp@666fefcb5d (2026-09-09).
Data as JSON: /api/errors/b8256868ccc82ddb.
Report an issue: GitHub.
Appendix: source
Thrown at VirtualApp/lib/src/main/java/com/lody/virtual/server/am/VActivityManagerService.java:240
while (iterator.hasNext()) {
ServiceRecord r = iterator.next();
if (r.process != null && r.process.pid == record.pid) {
iterator.remove();
}
}
mMainStack.processDied(record);
}
}
@Override
public IBinder acquireProviderClient(int userId, ProviderInfo info) {
ProcessRecord callerApp;
synchronized (mPidsSelfLocked) {
callerApp = findProcessLocked(getCallingPid());
}
if (callerApp == null) {
throw new SecurityException("Who are you?");
}
String processName = info.processName;
ProcessRecord r;
synchronized (this) {
r = startProcessIfNeedLocked(processName, userId, info.packageName);
}
if (r != null && r.client.asBinder().isBinderAlive()) {
try {
return r.client.acquireProviderClient(info);
} catch (RemoteException e) {
e.printStackTrace();
}
}
return null;
}
@Override
public ComponentName getCallingActivity(int userId, IBinder token) {View on GitHub (pinned to 666fefcb5d)