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

Commit 5b6e11c7 authored by Weilin Xu's avatar Weilin Xu Committed by Android (Google) Code Review
Browse files

Merge "Add adb shell command to default AIDL"

parents 886c967b 97203b0f
Loading
Loading
Loading
Loading
+315 −0
Original line number Diff line number Diff line
@@ -22,11 +22,15 @@
#include <aidl/android/hardware/broadcastradio/Result.h>

#include <android-base/logging.h>
#include <android-base/strings.h>

#include <private/android_filesystem_config.h>

namespace aidl::android::hardware::broadcastradio {

using ::aidl::android::hardware::broadcastradio::utils::resultToInt;
using ::aidl::android::hardware::broadcastradio::utils::tunesTo;
using ::android::base::EqualsIgnoreCase;
using ::ndk::ScopedAStatus;
using ::std::literals::chrono_literals::operator""ms;
using ::std::literals::chrono_literals::operator""s;
@@ -83,6 +87,15 @@ ProgramInfo makeSampleProgramInfo(const ProgramSelector& selector) {
    return info;
}

static bool checkDumpCallerHasWritePermissions(int fd) {
    uid_t uid = AIBinder_getCallingUid();
    if (uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM) {
        return true;
    }
    dprintf(fd, "BroadcastRadio HAL dump must be root, shell or system\n");
    return false;
}

}  // namespace

BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio)
@@ -470,4 +483,306 @@ ScopedAStatus BroadcastRadio::registerAnnouncementListener(
            "registering announcementListener is not supported");
}

binder_status_t BroadcastRadio::dump(int fd, const char** args, uint32_t numArgs) {
    if (numArgs == 0) {
        return dumpsys(fd);
    }

    string option = string(args[0]);
    if (EqualsIgnoreCase(option, "--help")) {
        return cmdHelp(fd);
    } else if (EqualsIgnoreCase(option, "--tune")) {
        return cmdTune(fd, args, numArgs);
    } else if (EqualsIgnoreCase(option, "--seek")) {
        return cmdSeek(fd, args, numArgs);
    } else if (EqualsIgnoreCase(option, "--step")) {
        return cmdStep(fd, args, numArgs);
    } else if (EqualsIgnoreCase(option, "--cancel")) {
        return cmdCancel(fd, numArgs);
    } else if (EqualsIgnoreCase(option, "--startProgramListUpdates")) {
        return cmdStartProgramListUpdates(fd, args, numArgs);
    } else if (EqualsIgnoreCase(option, "--stopProgramListUpdates")) {
        return cmdStopProgramListUpdates(fd, numArgs);
    }
    dprintf(fd, "Invalid option: %s\n", option.c_str());
    return STATUS_BAD_VALUE;
}

binder_status_t BroadcastRadio::dumpsys(int fd) {
    if (!checkDumpCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    lock_guard<mutex> lk(mMutex);
    dprintf(fd, "AmFmRegionConfig: %s\n", mAmFmConfig.toString().c_str());
    dprintf(fd, "Properties: %s \n", mProperties.toString().c_str());
    if (mIsTuneCompleted) {
        dprintf(fd, "Tune completed\n");
    } else {
        dprintf(fd, "Tune not completed\n");
    }
    if (mCallback == nullptr) {
        dprintf(fd, "No ITunerCallback registered\n");
    } else {
        dprintf(fd, "ITunerCallback registered\n");
    }
    dprintf(fd, "CurrentProgram: %s \n", mCurrentProgram.toString().c_str());
    return STATUS_OK;
}

binder_status_t BroadcastRadio::cmdHelp(int fd) const {
    dprintf(fd, "Usage: \n\n");
    dprintf(fd, "[no args]: dumps focus listener / gain callback registered status\n");
    dprintf(fd, "--help: shows this help\n");
    dprintf(fd,
            "--tune amfm <FREQUENCY>: tunes amfm radio to frequency (in Hz) specified: "
            "frequency (int) \n"
            "--tune dab <SID> <ENSEMBLE>: tunes dab radio to sid and ensemble specified: "
            "sidExt (int), ensemble (int) \n");
    dprintf(fd,
            "--seek [up|down] <SKIP_SUB_CHANNEL>: seek with direction (up or down) and "
            "option whether skipping sub channel: "
            "skipSubChannel (string, should be either \"true\" or \"false\")\n");
    dprintf(fd, "--step [up|down]: step in direction (up or down) specified\n");
    dprintf(fd, "--cancel: cancel current pending tune, step, and seek\n");
    dprintf(fd,
            "--startProgramListUpdates <IDENTIFIER_TYPES> <IDENTIFIERS> <INCLUDE_CATEGORIES> "
            "<EXCLUDE_MODIFICATIONS>: start update program list with the filter specified: "
            "identifier types (string, in format <TYPE>,<TYPE>,...,<TYPE> or \"null\" (if empty), "
            "where TYPE is int), "
            "program identifiers (string, in format "
            "<TYPE>:<VALUE>,<TYPE>:<VALUE>,...,<TYPE>:<VALUE> or \"null\" (if empty), "
            "where TYPE is int and VALUE is long), "
            "includeCategories (string, should be either \"true\" or \"false\"), "
            "excludeModifications (string, should be either \"true\" or \"false\")\n");
    dprintf(fd, "--stopProgramListUpdates: stop current pending program list updates\n");
    dprintf(fd,
            "Note on <TYPE> for --startProgramList command: it is int for identifier type. "
            "Please see broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl "
            "for its definition.\n");
    dprintf(fd,
            "Note on <VALUE> for --startProgramList command: it is long type for identifier value. "
            "Please see broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl "
            "for its value.\n");

    return STATUS_OK;
}

binder_status_t BroadcastRadio::cmdTune(int fd, const char** args, uint32_t numArgs) {
    if (!checkDumpCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    if (numArgs != 3 && numArgs != 4) {
        dprintf(fd,
                "Invalid number of arguments: please provide --tune amfm <FREQUENCY> "
                "or --tune dab <SID> <ENSEMBLE>\n");
        return STATUS_BAD_VALUE;
    }
    bool isDab = false;
    if (EqualsIgnoreCase(string(args[1]), "dab")) {
        isDab = true;
    } else if (!EqualsIgnoreCase(string(args[1]), "amfm")) {
        dprintf(fd, "Unknown radio type provided with tune: %s\n", args[1]);
        return STATUS_BAD_VALUE;
    }
    ProgramSelector sel = {};
    if (isDab) {
        if (numArgs != 4) {
            dprintf(fd,
                    "Invalid number of arguments: please provide --tune dab <SID> <ENSEMBLE>\n");
            return STATUS_BAD_VALUE;
        }
        int sid;
        if (!utils::parseArgInt(string(args[2]), &sid)) {
            dprintf(fd, "Non-integer sid provided with tune: %s\n", string(args[2]).c_str());
            return STATUS_BAD_VALUE;
        }
        int ensemble;
        if (!utils::parseArgInt(string(args[3]), &ensemble)) {
            dprintf(fd, "Non-integer ensemble provided with tune: %s\n", string(args[3]).c_str());
            return STATUS_BAD_VALUE;
        }
        sel = utils::makeSelectorDab(sid, ensemble);
    } else {
        if (numArgs != 3) {
            dprintf(fd, "Invalid number of arguments: please provide --tune amfm <FREQUENCY>\n");
            return STATUS_BAD_VALUE;
        }
        int freq;
        if (!utils::parseArgInt(string(args[2]), &freq)) {
            dprintf(fd, "Non-integer frequency provided with tune: %s\n", string(args[2]).c_str());
            return STATUS_BAD_VALUE;
        }
        sel = utils::makeSelectorAmfm(freq);
    }

    auto tuneResult = tune(sel);
    if (!tuneResult.isOk()) {
        dprintf(fd, "Unable to tune %s radio to %s\n", args[1], sel.toString().c_str());
        return STATUS_BAD_VALUE;
    }
    dprintf(fd, "Tune %s radio to %s \n", args[1], sel.toString().c_str());
    return STATUS_OK;
}

binder_status_t BroadcastRadio::cmdSeek(int fd, const char** args, uint32_t numArgs) {
    if (!checkDumpCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    if (numArgs != 3) {
        dprintf(fd,
                "Invalid number of arguments: please provide --seek <DIRECTION> "
                "<SKIP_SUB_CHANNEL>\n");
        return STATUS_BAD_VALUE;
    }
    string seekDirectionIn = string(args[1]);
    bool seekDirectionUp;
    if (!utils::parseArgDirection(seekDirectionIn, &seekDirectionUp)) {
        dprintf(fd, "Invalid direction (\"up\" or \"down\") provided with seek: %s\n",
                seekDirectionIn.c_str());
        return STATUS_BAD_VALUE;
    }
    string skipSubChannelIn = string(args[2]);
    bool skipSubChannel;
    if (!utils::parseArgBool(skipSubChannelIn, &skipSubChannel)) {
        dprintf(fd, "Invalid skipSubChannel (\"true\" or \"false\") provided with seek: %s\n",
                skipSubChannelIn.c_str());
        return STATUS_BAD_VALUE;
    }

    auto seekResult = seek(seekDirectionUp, skipSubChannel);
    if (!seekResult.isOk()) {
        dprintf(fd, "Unable to seek in %s direction\n", seekDirectionIn.c_str());
        return STATUS_BAD_VALUE;
    }
    dprintf(fd, "Seek in %s direction\n", seekDirectionIn.c_str());
    return STATUS_OK;
}

binder_status_t BroadcastRadio::cmdStep(int fd, const char** args, uint32_t numArgs) {
    if (!checkDumpCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    if (numArgs != 2) {
        dprintf(fd, "Invalid number of arguments: please provide --step <DIRECTION>\n");
        return STATUS_BAD_VALUE;
    }
    string stepDirectionIn = string(args[1]);
    bool stepDirectionUp;
    if (!utils::parseArgDirection(stepDirectionIn, &stepDirectionUp)) {
        dprintf(fd, "Invalid direction (\"up\" or \"down\") provided with step: %s\n",
                stepDirectionIn.c_str());
        return STATUS_BAD_VALUE;
    }

    auto stepResult = step(stepDirectionUp);
    if (!stepResult.isOk()) {
        dprintf(fd, "Unable to step in %s direction\n", stepDirectionIn.c_str());
        return STATUS_BAD_VALUE;
    }
    dprintf(fd, "Step in %s direction\n", stepDirectionIn.c_str());
    return STATUS_OK;
}

binder_status_t BroadcastRadio::cmdCancel(int fd, uint32_t numArgs) {
    if (!checkDumpCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    if (numArgs != 1) {
        dprintf(fd,
                "Invalid number of arguments: please provide --cancel "
                "only and no more arguments\n");
        return STATUS_BAD_VALUE;
    }

    auto cancelResult = cancel();
    if (!cancelResult.isOk()) {
        dprintf(fd, "Unable to cancel pending tune, seek, and step\n");
        return STATUS_BAD_VALUE;
    }
    dprintf(fd, "Canceled pending tune, seek, and step\n");
    return STATUS_OK;
}

binder_status_t BroadcastRadio::cmdStartProgramListUpdates(int fd, const char** args,
                                                           uint32_t numArgs) {
    if (!checkDumpCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    if (numArgs != 5) {
        dprintf(fd,
                "Invalid number of arguments: please provide --startProgramListUpdates "
                "<IDENTIFIER_TYPES> <IDENTIFIERS> <INCLUDE_CATEGORIES> "
                "<EXCLUDE_MODIFICATIONS>\n");
        return STATUS_BAD_VALUE;
    }
    string filterTypesStr = string(args[1]);
    std::vector<IdentifierType> filterTypeList;
    if (!EqualsIgnoreCase(filterTypesStr, "null") &&
        !utils::parseArgIdentifierTypeArray(filterTypesStr, &filterTypeList)) {
        dprintf(fd,
                "Invalid identifier types provided with startProgramListUpdates: %s, "
                "should be: <TYPE>,<TYPE>,...,<TYPE>\n",
                filterTypesStr.c_str());
        return STATUS_BAD_VALUE;
    }
    string filtersStr = string(args[2]);
    std::vector<ProgramIdentifier> filterList;
    if (!EqualsIgnoreCase(filtersStr, "null") &&
        !utils::parseProgramIdentifierList(filtersStr, &filterList)) {
        dprintf(fd,
                "Invalid program identifiers provided with startProgramListUpdates: %s, "
                "should be: <TYPE>:<VALUE>,<TYPE>:<VALUE>,...,<TYPE>:<VALUE>\n",
                filtersStr.c_str());
        return STATUS_BAD_VALUE;
    }
    string includeCategoriesStr = string(args[3]);
    bool includeCategories;
    if (!utils::parseArgBool(includeCategoriesStr, &includeCategories)) {
        dprintf(fd,
                "Invalid includeCategories (\"true\" or \"false\") "
                "provided with startProgramListUpdates : %s\n",
                includeCategoriesStr.c_str());
        return STATUS_BAD_VALUE;
    }
    string excludeModificationsStr = string(args[4]);
    bool excludeModifications;
    if (!utils::parseArgBool(excludeModificationsStr, &excludeModifications)) {
        dprintf(fd,
                "Invalid excludeModifications(\"true\" or \"false\") "
                "provided with startProgramListUpdates : %s\n",
                excludeModificationsStr.c_str());
        return STATUS_BAD_VALUE;
    }
    ProgramFilter filter = {filterTypeList, filterList, includeCategories, excludeModifications};

    auto updateResult = startProgramListUpdates(filter);
    if (!updateResult.isOk()) {
        dprintf(fd, "Unable to start program list update for filter %s \n",
                filter.toString().c_str());
        return STATUS_BAD_VALUE;
    }
    dprintf(fd, "Start program list update for filter %s\n", filter.toString().c_str());
    return STATUS_OK;
}

binder_status_t BroadcastRadio::cmdStopProgramListUpdates(int fd, uint32_t numArgs) {
    if (!checkDumpCallerHasWritePermissions(fd)) {
        return STATUS_PERMISSION_DENIED;
    }
    if (numArgs != 1) {
        dprintf(fd,
                "Invalid number of arguments: please provide --stopProgramListUpdates "
                "only and no more arguments\n");
        return STATUS_BAD_VALUE;
    }

    auto stopResult = stopProgramListUpdates();
    if (!stopResult.isOk()) {
        dprintf(fd, "Unable to stop pending program list update\n");
        return STATUS_BAD_VALUE;
    }
    dprintf(fd, "Stop pending program list update\n");
    return STATUS_OK;
}

}  // namespace aidl::android::hardware::broadcastradio
+11 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ class BroadcastRadio final : public BnBroadcastRadio {
            const std::shared_ptr<IAnnouncementListener>& listener,
            const std::vector<AnnouncementType>& enabled,
            std::shared_ptr<ICloseHandle>* returnCloseHandle) override;
    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;

  private:
    const VirtualRadio& mVirtualRadio;
@@ -77,6 +78,16 @@ class BroadcastRadio final : public BnBroadcastRadio {
    std::optional<AmFmBandRange> getAmFmRangeLocked() const;
    void cancelLocked();
    ProgramInfo tuneInternalLocked(const ProgramSelector& sel);

    binder_status_t cmdHelp(int fd) const;
    binder_status_t cmdTune(int fd, const char** args, uint32_t numArgs);
    binder_status_t cmdSeek(int fd, const char** args, uint32_t numArgs);
    binder_status_t cmdStep(int fd, const char** args, uint32_t numArgs);
    binder_status_t cmdCancel(int fd, uint32_t numArgs);
    binder_status_t cmdStartProgramListUpdates(int fd, const char** args, uint32_t numArgs);
    binder_status_t cmdStopProgramListUpdates(int fd, uint32_t numArgs);

    binder_status_t dumpsys(int fd);
};

}  // namespace aidl::android::hardware::broadcastradio
+68 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
#include "broadcastradio-utils-aidl/Utils.h"

#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>

#include <math/HashCombine.h>

@@ -28,6 +30,7 @@ namespace utils {

namespace {

using ::android::base::EqualsIgnoreCase;
using ::std::string;
using ::std::vector;

@@ -464,6 +467,71 @@ ProgramIdentifier makeHdRadioStationName(const string& name) {
    return makeIdentifier(IdentifierType::HD_STATION_NAME, val);
}

IdentifierType getType(int typeAsInt) {
    return static_cast<IdentifierType>(typeAsInt);
}

bool parseArgInt(const string& s, int* out) {
    return ::android::base::ParseInt(s, out);
}

bool parseArgLong(const std::string& s, long* out) {
    return ::android::base::ParseInt(s, out);
}

bool parseArgBool(const string& s, bool* out) {
    if (EqualsIgnoreCase(s, "true")) {
        *out = true;
    } else if (EqualsIgnoreCase(s, "false")) {
        *out = false;
    } else {
        return false;
    }
    return true;
}

bool parseArgDirection(const string& s, bool* out) {
    if (EqualsIgnoreCase(s, "up")) {
        *out = true;
    } else if (EqualsIgnoreCase(s, "down")) {
        *out = false;
    } else {
        return false;
    }
    return true;
}

bool parseArgIdentifierTypeArray(const string& s, vector<IdentifierType>* out) {
    for (const string& val : ::android::base::Split(s, ",")) {
        int outInt;
        if (!parseArgInt(val, &outInt)) {
            return false;
        }
        out->push_back(getType(outInt));
    }
    return true;
}

bool parseProgramIdentifierList(const std::string& s, vector<ProgramIdentifier>* out) {
    for (const string& idStr : ::android::base::Split(s, ",")) {
        const vector<string> idStrPair = ::android::base::Split(idStr, ":");
        if (idStrPair.size() != 2) {
            return false;
        }
        int idType;
        if (!parseArgInt(idStrPair[0], &idType)) {
            return false;
        }
        long idVal;
        if (!parseArgLong(idStrPair[1], &idVal)) {
            return false;
        }
        ProgramIdentifier id = {getType(idType), idVal};
        out->push_back(id);
    }
    return true;
}

}  // namespace utils

utils::IdentifierIterator begin(const ProgramSelector& sel) {
+14 −0
Original line number Diff line number Diff line
@@ -166,6 +166,20 @@ inline std::string vectorToString(const std::vector<aidl_type>& in_values) {
                           });
}

IdentifierType getType(int typeAsInt);

bool parseArgInt(const std::string& s, int* out);

bool parseArgLong(const std::string& s, long* out);

bool parseArgBool(const std::string& s, bool* out);

bool parseArgDirection(const std::string& s, bool* out);

bool parseArgIdentifierTypeArray(const std::string& s, std::vector<IdentifierType>* out);

bool parseProgramIdentifierList(const std::string& s, std::vector<ProgramIdentifier>* out);

}  // namespace utils

utils::IdentifierIterator begin(const ProgramSelector& sel);