@ -22,6 +22,9 @@
# include <binder/PermissionCache.h>
# include "mediautils/ServiceUtilities.h"
# include <iterator>
# include <algorithm>
/* When performing permission checks we do not use permission cache for
* runtime permissions ( protection level dangerous ) as they may change at
* runtime . All other permissions ( protection level normal and dangerous )
@ -220,4 +223,85 @@ status_t checkIMemory(const sp<IMemory>& iMemory)
return NO_ERROR ;
}
sp < content : : pm : : IPackageManagerNative > MediaPackageManager : : retreivePackageManager ( ) {
const sp < IServiceManager > sm = defaultServiceManager ( ) ;
if ( sm = = nullptr ) {
ALOGW ( " %s: failed to retrieve defaultServiceManager " , __func__ ) ;
return nullptr ;
}
sp < IBinder > packageManager = sm - > checkService ( String16 ( nativePackageManagerName ) ) ;
if ( packageManager = = nullptr ) {
ALOGW ( " %s: failed to retrieve native package manager " , __func__ ) ;
return nullptr ;
}
return interface_cast < content : : pm : : IPackageManagerNative > ( packageManager ) ;
}
std : : optional < bool > MediaPackageManager : : doIsAllowed ( uid_t uid ) {
if ( mPackageManager = = nullptr ) {
/** Can not fetch package manager at construction it may not yet be registered. */
mPackageManager = retreivePackageManager ( ) ;
if ( mPackageManager = = nullptr ) {
ALOGW ( " %s: Playback capture is denied as package manager is not reachable " , __func__ ) ;
return std : : nullopt ;
}
}
std : : vector < std : : string > packageNames ;
auto status = mPackageManager - > getNamesForUids ( { ( int32_t ) uid } , & packageNames ) ;
if ( ! status . isOk ( ) ) {
ALOGW ( " %s: Playback capture is denied for uid %u as the package names could not be "
" retrieved from the package manager: %s " , __func__ , uid , status . toString8 ( ) . c_str ( ) ) ;
return std : : nullopt ;
}
if ( packageNames . empty ( ) ) {
ALOGW ( " %s: Playback capture for uid %u is denied as no package name could be retrieved "
" from the package manager: %s " , __func__ , uid , status . toString8 ( ) . c_str ( ) ) ;
return std : : nullopt ;
}
std : : vector < bool > isAllowed ;
status = mPackageManager - > isAudioPlaybackCaptureAllowed ( packageNames , & isAllowed ) ;
if ( ! status . isOk ( ) ) {
ALOGW ( " %s: Playback capture is denied for uid %u as the manifest property could not be "
" retrieved from the package manager: %s " , __func__ , uid , status . toString8 ( ) . c_str ( ) ) ;
return std : : nullopt ;
}
if ( packageNames . size ( ) ! = isAllowed . size ( ) ) {
ALOGW ( " %s: Playback capture is denied for uid %u as the package manager returned incoherent "
" response size: %zu != %zu " , __func__ , uid , packageNames . size ( ) , isAllowed . size ( ) ) ;
return std : : nullopt ;
}
// Zip together packageNames and isAllowed for debug logs
Packages & packages = mDebugLog [ uid ] ;
packages . resize ( packageNames . size ( ) ) ; // Reuse all objects
std : : transform ( begin ( packageNames ) , end ( packageNames ) , begin ( isAllowed ) ,
begin ( packages ) , [ ] ( auto & name , bool isAllowed ) - > Package {
return { std : : move ( name ) , isAllowed } ;
} ) ;
// Only allow playback record if all packages in this UID allow it
bool playbackCaptureAllowed = std : : all_of ( begin ( isAllowed ) , end ( isAllowed ) ,
[ ] ( bool b ) { return b ; } ) ;
return playbackCaptureAllowed ;
}
void MediaPackageManager : : dump ( int fd , int spaces ) const {
dprintf ( fd , " %*sAllow playback capture log: \n " , spaces , " " ) ;
if ( mPackageManager = = nullptr ) {
dprintf ( fd , " %*sNo package manager \n " , spaces + 2 , " " ) ;
}
dprintf ( fd , " %*sPackage manager errors: %u \n " , spaces + 2 , " " , mPackageManagerErrors ) ;
for ( const auto & uidCache : mDebugLog ) {
for ( const auto & package : std : : get < Packages > ( uidCache ) ) {
dprintf ( fd , " %*s- uid=%5u, allowPlaybackCapture=%s, packageName=%s \n " , spaces + 2 , " " ,
std : : get < const uid_t > ( uidCache ) ,
package . playbackCaptureAllowed ? " true " : " false " ,
package . name . c_str ( ) ) ;
}
}
}
} // namespace android