Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6e4e03ed authored by riddle_hsu's avatar riddle_hsu Committed by Steve Kondik
Browse files

[ActivityManager] Ensure provider external access count will be released.

Sympton: Oom-adj of provider process will be always 0.

Root Cause: Exception happend in openContentUri
may not call removeContentProviderExternalUnchecked.

Flow:
application [MediaPlayer.setDataSource(Context context, Uri uri)]
    uri is invalid, IOException will be caught and below log will appear:
    "Couldn't open file on client side, trying server side"
    Continue to call setDataSource(String path, Map<String, String> headers)
 ->mediaserver [MediaPlayerService::Client::setDataSource]
    setDataSource(httpService, url, headers) calls openContentProviderFile
 ->system_server (ActivityManagerService) [openContentUri]
    Increase externalProcessNoHandleCount for media provider.
    Call [openFile] to media provider.
 ->android.process.media [check permission for openFile]
    enforceReadPermissionInner
 ->system_server [checkComponentPermission]
    Use mediaserver's uid to check READ_EXTERNAL_STORAGE
      -> not granted due to it is pure native process, not a known package.
    Throw security exception then the flow of openContentUri is broke.
    And externalProcessNoHandleCount is unable to decrease.

Application sample code:
 String invalidId = "54321";
 Uri externalUri = MediaStore.Files.getContentUri("external");
 Uri uri = Uri.withAppendedPath(externalUri, invalidId);
 mediaPlayer.setDataSource(mContext, uri);

Solution: Move removeContentProviderExternalUnchecked to finally block.

Change-Id: I75eec1f9631e9c6bb18449946d707d51ac21e8a7
parent 63da2824
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -10171,10 +10171,9 @@ public final class ActivityManagerService extends ActivityManagerNative
            } finally {
                // Ensure that whatever happens, we clean up the identity state
                sCallerIdentity.remove();
            }
            // We've got the fd now, so we're done with the provider.
                // Ensure we're done with the provider.
                removeContentProviderExternalUnchecked(name, null, userId);
            }
        } else {
            Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
        }