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

Commit 09603c39 authored by Kevin Rocard's avatar Kevin Rocard Committed by Android (Google) Code Review
Browse files

Merge "Check for app manifest opt-out from playback capture"

parents d83b08ac 8be94978
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ LOCAL_SHARED_LIBRARIES := \
	libhwbinder \
	libmedia \
	libmedialogservice \
	libmediautils \
	libnbaio \
	libnblog \
	libsoundtriggerservice \
+84 −0
Original line number Diff line number Diff line
@@ -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
+36 −0
Original line number Diff line number Diff line
@@ -14,13 +14,22 @@
 * limitations under the License.
 */

#ifndef ANDROID_MEDIAUTILS_SERVICEUTILITIES_H
#define ANDROID_MEDIAUTILS_SERVICEUTILITIES_H

#include <unistd.h>

#include <android/content/pm/IPackageManagerNative.h>
#include <binder/IMemory.h>
#include <binder/PermissionController.h>
#include <cutils/multiuser.h>
#include <private/android_filesystem_config.h>

#include <map>
#include <optional>
#include <string>
#include <vector>

namespace android {

// Audio permission utilities
@@ -72,4 +81,31 @@ bool modifyDefaultAudioEffectsAllowed();
bool dumpAllowed();
bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
status_t checkIMemory(const sp<IMemory>& iMemory);

class MediaPackageManager {
public:
    /** Query the PackageManager to check if all apps of an UID allow playback capture. */
    bool allowPlaybackCapture(uid_t uid) {
        auto result = doIsAllowed(uid);
        if (!result) {
            mPackageManagerErrors++;
        }
        return result.value_or(false);
    }
    void dump(int fd, int spaces = 0) const;
private:
    static constexpr const char* nativePackageManagerName = "package_native";
    std::optional<bool> doIsAllowed(uid_t uid);
    sp<content::pm::IPackageManagerNative> retreivePackageManager();
    sp<content::pm::IPackageManagerNative> mPackageManager; // To check apps manifest
    uint_t mPackageManagerErrors = 0;
    struct Package {
        std::string name;
        bool playbackCaptureAllowed = false;
    };
    using Packages = std::vector<Package>;
    std::map<uid_t, Packages> mDebugLog;
};
}

#endif // ANDROID_MEDIAUTILS_SERVICEUTILITIES_H
+1 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ LOCAL_STATIC_LIBRARIES := \
LOCAL_SHARED_LIBRARIES += libmedia_helper
LOCAL_SHARED_LIBRARIES += libmediametrics

LOCAL_SHARED_LIBRARIES += libhidlbase libxml2
LOCAL_SHARED_LIBRARIES += libbinder libhidlbase libxml2

ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
+8 −5
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
#include "AudioPolicyService.h"
#include "TypeConverter.h"
#include <media/MediaAnalyticsItem.h>
#include <mediautils/ServiceUtilities.h>
#include <media/AudioPolicy.h>
#include <utils/Log.h>

@@ -167,7 +166,7 @@ audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream)
    return mAudioPolicyManager->getOutput(stream);
}

status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *originalAttr,
                                              audio_io_handle_t *output,
                                              audio_session_t session,
                                              audio_stream_type_t *stream,
@@ -191,9 +190,13 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
                "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid);
        uid = callingUid;
    }
    audio_attributes_t attr = *originalAttr;
    if (!mPackageManager.allowPlaybackCapture(uid)) {
        attr.flags |= AUDIO_FLAG_NO_CAPTURE;
    }
    audio_output_flags_t originalFlags = flags;
    AutoCallerClear acc;
    status_t result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
    status_t result = mAudioPolicyManager->getOutputForAttr(&attr, output, session, stream, uid,
                                                 config,
                                                 &flags, selectedDeviceId, portId,
                                                 secondaryOutputs);
@@ -209,14 +212,14 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
        *selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
        *portId = AUDIO_PORT_HANDLE_NONE;
        secondaryOutputs->clear();
        result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, config,
        result = mAudioPolicyManager->getOutputForAttr(&attr, output, session, stream, uid, config,
                                                       &flags, selectedDeviceId, portId,
                                                       secondaryOutputs);
    }

    if (result == NO_ERROR) {
        sp <AudioPlaybackClient> client =
            new AudioPlaybackClient(*attr, *output, uid, pid, session, *selectedDeviceId, *stream);
            new AudioPlaybackClient(attr, *output, uid, pid, session, *selectedDeviceId, *stream);
        mAudioPlaybackClients.add(*portId, client);
    }
    return result;
Loading