Merge "Make refreshTimestamp atomic." into main
diff --git a/audio/aidl/default/include/core-impl/StreamPrimary.h b/audio/aidl/default/include/core-impl/StreamPrimary.h
index abc119c..145c3c4 100644
--- a/audio/aidl/default/include/core-impl/StreamPrimary.h
+++ b/audio/aidl/default/include/core-impl/StreamPrimary.h
@@ -27,13 +27,18 @@
public:
StreamPrimary(StreamContext* context, const Metadata& metadata);
+ ::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
+ ::android::status_t refinePosition(StreamDescriptor::Position* position) override;
protected:
std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
const bool mIsAsynchronous;
+ long mStartTimeNs = 0;
+ long mFramesSinceStart = 0;
+ bool mSkipNextTransfer = false;
};
class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp
index 7e3bdd4..b22ef32 100644
--- a/audio/aidl/default/primary/StreamPrimary.cpp
+++ b/audio/aidl/default/primary/StreamPrimary.cpp
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-#include <chrono>
-
#define LOG_TAG "AHAL_StreamPrimary"
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <audio_utils/clock.h>
+#include <error/Result.h>
#include <error/expected_utils.h>
#include "PrimaryMixer.h"
@@ -43,26 +42,52 @@
context->startStreamDataProcessor();
}
+::android::status_t StreamPrimary::start() {
+ RETURN_STATUS_IF_ERROR(StreamAlsa::start());
+ mStartTimeNs = ::android::uptimeNanos();
+ mFramesSinceStart = 0;
+ mSkipNextTransfer = false;
+ return ::android::OK;
+}
+
::android::status_t StreamPrimary::transfer(void* buffer, size_t frameCount,
size_t* actualFrameCount, int32_t* latencyMs) {
- auto start = std::chrono::steady_clock::now();
- if (auto status = StreamAlsa::transfer(buffer, frameCount, actualFrameCount, latencyMs);
- status != ::android::OK) {
- return status;
- }
// This is a workaround for the emulator implementation which has a host-side buffer
- // and this can result in reading faster than real time.
- if (mIsInput && !mIsAsynchronous) {
- auto recordDurationUs = std::chrono::duration_cast<std::chrono::microseconds>(
- std::chrono::steady_clock::now() - start);
- const long projectedVsObservedOffsetUs =
- *actualFrameCount * MICROS_PER_SECOND / mContext.getSampleRate() -
- recordDurationUs.count();
- if (projectedVsObservedOffsetUs > 0) {
- LOG(VERBOSE) << __func__ << ": sleeping for " << projectedVsObservedOffsetUs << " us";
- usleep(projectedVsObservedOffsetUs);
- }
+ // and is not being able to achieve real-time behavior similar to ADSPs (b/302587331).
+ if (!mSkipNextTransfer) {
+ RETURN_STATUS_IF_ERROR(
+ StreamAlsa::transfer(buffer, frameCount, actualFrameCount, latencyMs));
+ } else {
+ LOG(DEBUG) << __func__ << ": skipping transfer (" << frameCount << " frames)";
+ *actualFrameCount = frameCount;
+ if (mIsInput) memset(buffer, 0, frameCount * mFrameSizeBytes);
+ mSkipNextTransfer = false;
}
+ if (!mIsAsynchronous) {
+ const long bufferDurationUs =
+ (*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
+ const auto totalDurationUs =
+ (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
+ mFramesSinceStart += *actualFrameCount;
+ const long totalOffsetUs =
+ mFramesSinceStart * MICROS_PER_SECOND / mContext.getSampleRate() - totalDurationUs;
+ LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs;
+ if (totalOffsetUs > 0) {
+ const long sleepTimeUs = std::min(totalOffsetUs, bufferDurationUs);
+ LOG(VERBOSE) << __func__ << ": sleeping for " << sleepTimeUs << " us";
+ usleep(sleepTimeUs);
+ } else {
+ mSkipNextTransfer = true;
+ }
+ } else {
+ LOG(VERBOSE) << __func__ << ": asynchronous transfer";
+ }
+ return ::android::OK;
+}
+
+::android::status_t StreamPrimary::refinePosition(StreamDescriptor::Position*) {
+ // Since not all data is actually sent to the HAL, use the position maintained by Stream class
+ // which accounts for all frames passed from / to the client.
return ::android::OK;
}
diff --git a/automotive/vehicle/aidl/impl/grpc/Android.bp b/automotive/vehicle/aidl/impl/grpc/Android.bp
index 06c9600..e5106f8 100644
--- a/automotive/vehicle/aidl/impl/grpc/Android.bp
+++ b/automotive/vehicle/aidl/impl/grpc/Android.bp
@@ -22,9 +22,11 @@
"aprotoc",
"protoc-gen-grpc-cpp-plugin",
],
- cmd: "$(location aprotoc) -I$$(dirname $(in)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+ cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_out=$(genDir) --cpp_out=$(genDir)",
srcs: [
"proto/VehicleServer.proto",
+ ":libprotobuf-internal-protos",
+ ":VehicleHalProtoFiles",
],
out: [
"VehicleServer.pb.h",
@@ -39,9 +41,11 @@
"aprotoc",
"protoc-gen-grpc-cpp-plugin",
],
- cmd: "$(location aprotoc) -I$$(dirname $(in)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+ cmd: "$(location aprotoc) -I$$(dirname $(location proto/VehicleServer.proto)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(location proto/VehicleServer.proto) --grpc_out=$(genDir) --cpp_out=$(genDir)",
srcs: [
"proto/VehicleServer.proto",
+ ":libprotobuf-internal-protos",
+ ":VehicleHalProtoFiles",
],
out: [
"VehicleServer.pb.cc",
diff --git a/broadcastradio/aidl/default/BroadcastRadio.cpp b/broadcastradio/aidl/default/BroadcastRadio.cpp
index 63073d7..f82e767 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.cpp
+++ b/broadcastradio/aidl/default/BroadcastRadio.cpp
@@ -48,6 +48,8 @@
inline constexpr std::chrono::seconds kListDelayTimeS = 1s;
// clang-format off
+const AmFmBandRange kFmFullBandRange = {65000, 108000, 10, 0};
+const AmFmBandRange kAmFullBandRange = {150, 30000, 1, 0};
const AmFmRegionConfig kDefaultAmFmConfig = {
{
{87500, 108000, 100, 100}, // FM
@@ -77,14 +79,71 @@
return prop;
}
+bool isDigitalProgramAllowed(const ProgramSelector& sel, bool forceAnalogFm, bool forceAnalogAm) {
+ if (sel.primaryId.type != IdentifierType::HD_STATION_ID_EXT) {
+ return true;
+ }
+ int32_t freq = static_cast<int32_t>(utils::getAmFmFrequency(sel));
+ bool isFm = freq >= kFmFullBandRange.lowerBound && freq <= kFmFullBandRange.upperBound;
+ return isFm ? !forceAnalogFm : !forceAnalogAm;
+}
+
+/**
+ * Checks whether a program selector is in the current band.
+ *
+ * <p>For an AM/FM program, this method checks whether it is in the current AM/FM band. For a
+ * program selector is also an HD program, it is also checked whether HD radio is enabled in the
+ * current AM/FM band. For a non-AM/FM program, the method will returns {@code true} directly.
+ * @param sel Program selector to be checked
+ * @param currentAmFmBandRange the current AM/FM band
+ * @param forceAnalogFm whether FM band is forced to be analog
+ * @param forceAnalogAm whether AM band is forced to be analog
+ * @return whether the program selector is in the current band if it is an AM/FM (including HD)
+ * selector, {@code true} otherwise
+ */
+bool isProgramInBand(const ProgramSelector& sel,
+ const std::optional<AmFmBandRange>& currentAmFmBandRange, bool forceAnalogFm,
+ bool forceAnalogAm) {
+ if (!utils::hasAmFmFrequency(sel)) {
+ return true;
+ }
+ if (!currentAmFmBandRange.has_value()) {
+ return false;
+ }
+ int32_t freq = static_cast<int32_t>(utils::getAmFmFrequency(sel));
+ if (freq < currentAmFmBandRange->lowerBound || freq > currentAmFmBandRange->upperBound) {
+ return false;
+ }
+ return isDigitalProgramAllowed(sel, forceAnalogFm, forceAnalogAm);
+}
+
// Makes ProgramInfo that does not point to any particular program
ProgramInfo makeSampleProgramInfo(const ProgramSelector& selector) {
ProgramInfo info = {};
info.selector = selector;
- info.logicallyTunedTo =
- utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ,
- utils::getId(selector, IdentifierType::AMFM_FREQUENCY_KHZ));
- info.physicallyTunedTo = info.logicallyTunedTo;
+ switch (info.selector.primaryId.type) {
+ case IdentifierType::AMFM_FREQUENCY_KHZ:
+ info.logicallyTunedTo = utils::makeIdentifier(
+ IdentifierType::AMFM_FREQUENCY_KHZ,
+ utils::getId(selector, IdentifierType::AMFM_FREQUENCY_KHZ));
+ info.physicallyTunedTo = info.logicallyTunedTo;
+ break;
+ case IdentifierType::HD_STATION_ID_EXT:
+ info.logicallyTunedTo = utils::makeIdentifier(IdentifierType::AMFM_FREQUENCY_KHZ,
+ utils::getAmFmFrequency(info.selector));
+ info.physicallyTunedTo = info.logicallyTunedTo;
+ break;
+ case IdentifierType::DAB_SID_EXT:
+ info.logicallyTunedTo = info.selector.primaryId;
+ info.physicallyTunedTo = utils::makeIdentifier(
+ IdentifierType::DAB_FREQUENCY_KHZ,
+ utils::getId(selector, IdentifierType::DAB_FREQUENCY_KHZ));
+ break;
+ default:
+ info.logicallyTunedTo = info.selector.primaryId;
+ info.physicallyTunedTo = info.logicallyTunedTo;
+ break;
+ }
return info;
}
@@ -112,6 +171,7 @@
} else {
mCurrentProgram = sel;
}
+ adjustAmFmRangeLocked();
}
}
@@ -124,8 +184,8 @@
if (full) {
*returnConfigs = {};
returnConfigs->ranges = vector<AmFmBandRange>({
- {65000, 108000, 10, 0}, // FM
- {150, 30000, 1, 0}, // AM
+ kFmFullBandRange,
+ kAmFullBandRange,
});
returnConfigs->fmDeemphasis =
AmFmRegionConfig::DEEMPHASIS_D50 | AmFmRegionConfig::DEEMPHASIS_D75;
@@ -171,14 +231,24 @@
VirtualProgram virtualProgram = {};
ProgramInfo programInfo;
- if (mVirtualRadio.getProgram(sel, &virtualProgram)) {
+ bool isProgramAllowed =
+ isDigitalProgramAllowed(sel, isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_FM),
+ isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_AM));
+ if (isProgramAllowed && mVirtualRadio.getProgram(sel, &virtualProgram)) {
mCurrentProgram = virtualProgram.selector;
programInfo = virtualProgram;
} else {
- mCurrentProgram = sel;
+ if (!isProgramAllowed) {
+ mCurrentProgram = utils::makeSelectorAmfm(utils::getAmFmFrequency(sel));
+ } else {
+ mCurrentProgram = sel;
+ }
programInfo = makeSampleProgramInfo(sel);
}
mIsTuneCompleted = true;
+ if (adjustAmFmRangeLocked()) {
+ startProgramListUpdatesLocked({});
+ }
return programInfo;
}
@@ -246,6 +316,102 @@
return ScopedAStatus::ok();
}
+bool BroadcastRadio::findNextLocked(const ProgramSelector& current, bool directionUp,
+ bool skipSubChannel, VirtualProgram* nextProgram) const {
+ if (mProgramList.empty()) {
+ return false;
+ }
+ // The list is not sorted here since it has already stored in VirtualRadio.
+ bool hasAmFmFrequency = utils::hasAmFmFrequency(current);
+ uint32_t currentFreq = hasAmFmFrequency ? utils::getAmFmFrequency(current) : 0;
+ auto found =
+ std::lower_bound(mProgramList.begin(), mProgramList.end(), VirtualProgram({current}));
+ if (directionUp) {
+ if (found < mProgramList.end() - 1) {
+ // When seeking up, tuner will jump to the first selector which is main program service
+ // greater than and of the same band as the current program selector in the program
+ // list (if not exist, jump to the first selector in the same band) for skipping
+ // sub-channels case or AM/FM without HD radio enabled case. Otherwise, the tuner will
+ // jump to the first selector which is greater than and of the same band as the current
+ // program selector.
+ if (utils::tunesTo(current, found->selector)) found++;
+ if (skipSubChannel && hasAmFmFrequency) {
+ auto firstFound = found;
+ while (utils::getAmFmFrequency(found->selector) == currentFreq) {
+ if (found < mProgramList.end() - 1) {
+ found++;
+ } else {
+ found = mProgramList.begin();
+ }
+ if (found == firstFound) {
+ // Only one main channel exists in the program list, the tuner cannot skip
+ // sub-channel to the next program selector.
+ return false;
+ }
+ }
+ }
+ } else {
+ // If the selector of current program is no less than all selectors of the same band or
+ // not found in the program list, seeking up should wrap the tuner to the first program
+ // selector of the same band in the program list.
+ found = mProgramList.begin();
+ }
+ } else {
+ if (found > mProgramList.begin() && found != mProgramList.end()) {
+ // When seeking down, tuner will jump to the first selector which is main program
+ // service less than and of the same band as the current program selector in the
+ // program list (if not exist, jump to the last main program service selector of the
+ // same band) for skipping sub-channels case or AM/FM without HD radio enabled case.
+ // Otherwise, the tuner will jump to the first selector less than and of the same band
+ // as the current program selector.
+ found--;
+ if (hasAmFmFrequency && utils::hasAmFmFrequency(found->selector)) {
+ uint32_t nextFreq = utils::getAmFmFrequency(found->selector);
+ if (nextFreq != currentFreq) {
+ jumpToFirstSubChannelLocked(found);
+ } else if (skipSubChannel) {
+ jumpToFirstSubChannelLocked(found);
+ auto firstFound = found;
+ if (found > mProgramList.begin()) {
+ found--;
+ } else {
+ found = mProgramList.end() - 1;
+ }
+ jumpToFirstSubChannelLocked(found);
+ if (found == firstFound) {
+ // Only one main channel exists in the program list, the tuner cannot skip
+ // sub-channel to the next program selector.
+ return false;
+ }
+ }
+ }
+ } else {
+ // If the selector of current program is no greater than all selectors of the same band
+ // or not found in the program list, seeking down should wrap the tuner to the last
+ // selector of the same band in the program list. If the last program selector in the
+ // program list is sub-channel and skipping sub-channels is needed, the tuner will jump
+ // to the last main program service of the same band in the program list.
+ found = mProgramList.end() - 1;
+ jumpToFirstSubChannelLocked(found);
+ }
+ }
+ *nextProgram = *found;
+ return true;
+}
+
+void BroadcastRadio::jumpToFirstSubChannelLocked(vector<VirtualProgram>::const_iterator& it) const {
+ if (!utils::hasAmFmFrequency(it->selector) || it == mProgramList.begin()) {
+ return;
+ }
+ uint32_t currentFrequency = utils::getAmFmFrequency(it->selector);
+ it--;
+ while (it != mProgramList.begin() && utils::hasAmFmFrequency(it->selector) &&
+ utils::getAmFmFrequency(it->selector) == currentFrequency) {
+ it--;
+ }
+ it++;
+}
+
ScopedAStatus BroadcastRadio::seek(bool directionUp, bool skipSubChannel) {
LOG(DEBUG) << __func__ << ": seek " << (directionUp ? "up" : "down") << " with skipSubChannel? "
<< (skipSubChannel ? "yes" : "no") << "...";
@@ -259,11 +425,21 @@
cancelLocked();
+ auto filterCb = [this](const VirtualProgram& program) {
+ return isProgramInBand(program.selector, mCurrentAmFmBandRange,
+ isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_FM),
+ isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_AM));
+ };
const auto& list = mVirtualRadio.getProgramList();
+ mProgramList.clear();
+ std::copy_if(list.begin(), list.end(), std::back_inserter(mProgramList), filterCb);
std::shared_ptr<ITunerCallback> callback = mCallback;
auto cancelTask = [callback]() { callback->onTuneFailed(Result::CANCELED, {}); };
- if (list.empty()) {
- mIsTuneCompleted = false;
+
+ VirtualProgram nextProgram = {};
+ bool foundNext = findNextLocked(mCurrentProgram, directionUp, skipSubChannel, &nextProgram);
+ mIsTuneCompleted = false;
+ if (!foundNext) {
auto task = [callback]() {
LOG(DEBUG) << "seek: program list is empty, seek couldn't stop";
@@ -274,31 +450,11 @@
return ScopedAStatus::ok();
}
- // The list is not sorted here since it has already stored in VirtualRadio.
- // If the list is not sorted in advance, it should be sorted here.
- const auto& current = mCurrentProgram;
- auto found = std::lower_bound(list.begin(), list.end(), VirtualProgram({current}));
- if (directionUp) {
- if (found < list.end() - 1) {
- if (tunesTo(current, found->selector)) found++;
- } else {
- found = list.begin();
- }
- } else {
- if (found > list.begin() && found != list.end()) {
- found--;
- } else {
- found = list.end() - 1;
- }
- }
- const ProgramSelector tuneTo = found->selector;
-
- mIsTuneCompleted = false;
- auto task = [this, tuneTo, callback]() {
+ auto task = [this, nextProgram, callback]() {
ProgramInfo programInfo = {};
{
lock_guard<mutex> lk(mMutex);
- programInfo = tuneInternalLocked(tuneTo);
+ programInfo = tuneInternalLocked(nextProgram.selector);
}
callback->onCurrentProgramInfoChanged(programInfo);
};
@@ -319,31 +475,33 @@
cancelLocked();
- if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ)) {
+ int64_t stepTo;
+ if (utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ)) {
+ stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ);
+ } else if (mCurrentProgram.primaryId.type == IdentifierType::HD_STATION_ID_EXT) {
+ stepTo = utils::getHdFrequency(mCurrentProgram);
+ } else {
LOG(WARNING) << __func__ << ": can't step in anything else than AM/FM";
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
resultToInt(Result::NOT_SUPPORTED), "cannot step in anything else than AM/FM");
}
- int64_t stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ);
- std::optional<AmFmBandRange> range = getAmFmRangeLocked();
- if (!range) {
- LOG(ERROR) << __func__ << ": can't find current band or tune operation is in process";
+ if (!mCurrentAmFmBandRange.has_value()) {
+ LOG(ERROR) << __func__ << ": can't find current band";
return ScopedAStatus::fromServiceSpecificErrorWithMessage(
- resultToInt(Result::INTERNAL_ERROR),
- "can't find current band or tune operation is in process");
+ resultToInt(Result::INTERNAL_ERROR), "can't find current band");
}
if (directionUp) {
- stepTo += range->spacing;
+ stepTo += mCurrentAmFmBandRange->spacing;
} else {
- stepTo -= range->spacing;
+ stepTo -= mCurrentAmFmBandRange->spacing;
}
- if (stepTo > range->upperBound) {
- stepTo = range->lowerBound;
+ if (stepTo > mCurrentAmFmBandRange->upperBound) {
+ stepTo = mCurrentAmFmBandRange->lowerBound;
}
- if (stepTo < range->lowerBound) {
- stepTo = range->upperBound;
+ if (stepTo < mCurrentAmFmBandRange->lowerBound) {
+ stepTo = mCurrentAmFmBandRange->upperBound;
}
mIsTuneCompleted = false;
@@ -380,16 +538,14 @@
return ScopedAStatus::ok();
}
-ScopedAStatus BroadcastRadio::startProgramListUpdates(const ProgramFilter& filter) {
- LOG(DEBUG) << __func__ << ": requested program list updates, filter = " << filter.toString()
- << "...";
-
- auto filterCb = [&filter](const VirtualProgram& program) {
- return utils::satisfies(filter, program.selector);
+void BroadcastRadio::startProgramListUpdatesLocked(const ProgramFilter& filter) {
+ auto filterCb = [&filter, this](const VirtualProgram& program) {
+ return utils::satisfies(filter, program.selector) &&
+ isProgramInBand(program.selector, mCurrentAmFmBandRange,
+ isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_FM),
+ isConfigFlagSetLocked(ConfigFlag::FORCE_ANALOG_AM));
};
- lock_guard<mutex> lk(mMutex);
-
cancelProgramListUpdateLocked();
const auto& list = mVirtualRadio.getProgramList();
@@ -415,6 +571,15 @@
callback->onProgramListUpdated(chunk);
};
mProgramListThread->schedule(task, kListDelayTimeS);
+}
+
+ScopedAStatus BroadcastRadio::startProgramListUpdates(const ProgramFilter& filter) {
+ LOG(DEBUG) << __func__ << ": requested program list updates, filter = " << filter.toString()
+ << "...";
+
+ lock_guard<mutex> lk(mMutex);
+
+ startProgramListUpdatesLocked(filter);
return ScopedAStatus::ok();
}
@@ -431,18 +596,28 @@
return ScopedAStatus::ok();
}
+bool BroadcastRadio::isConfigFlagSetLocked(ConfigFlag flag) const {
+ int flagBit = static_cast<int>(flag);
+ return ((mConfigFlagValues >> flagBit) & 1) == 1;
+}
+
ScopedAStatus BroadcastRadio::isConfigFlagSet(ConfigFlag flag, bool* returnIsSet) {
LOG(DEBUG) << __func__ << ": flag = " << toString(flag);
- int flagBit = static_cast<int>(flag);
+ if (flag == ConfigFlag::FORCE_ANALOG) {
+ flag = ConfigFlag::FORCE_ANALOG_FM;
+ }
lock_guard<mutex> lk(mMutex);
- *returnIsSet = ((mConfigFlagValues >> flagBit) & 1) == 1;
+ *returnIsSet = isConfigFlagSetLocked(flag);
return ScopedAStatus::ok();
}
ScopedAStatus BroadcastRadio::setConfigFlag(ConfigFlag flag, bool value) {
LOG(DEBUG) << __func__ << ": flag = " << toString(flag) << ", value = " << value;
+ if (flag == ConfigFlag::FORCE_ANALOG) {
+ flag = ConfigFlag::FORCE_ANALOG_FM;
+ }
int flagBitMask = 1 << (static_cast<int>(flag));
lock_guard<mutex> lk(mMutex);
if (value) {
@@ -450,6 +625,9 @@
} else {
mConfigFlagValues &= ~flagBitMask;
}
+ if (flag == ConfigFlag::FORCE_ANALOG_AM || flag == ConfigFlag::FORCE_ANALOG_FM) {
+ startProgramListUpdatesLocked({});
+ }
return ScopedAStatus::ok();
}
@@ -468,24 +646,25 @@
return ScopedAStatus::ok();
}
-std::optional<AmFmBandRange> BroadcastRadio::getAmFmRangeLocked() const {
- if (!mIsTuneCompleted) {
- LOG(WARNING) << __func__ << ": tune operation is in process";
- return {};
- }
- if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ)) {
+bool BroadcastRadio::adjustAmFmRangeLocked() {
+ bool hasBandBefore = mCurrentAmFmBandRange.has_value();
+ if (!utils::hasAmFmFrequency(mCurrentProgram)) {
LOG(WARNING) << __func__ << ": current program does not has AMFM_FREQUENCY_KHZ identifier";
- return {};
+ mCurrentAmFmBandRange.reset();
+ return hasBandBefore;
}
- int64_t freq = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY_KHZ);
+ int32_t freq = static_cast<int32_t>(utils::getAmFmFrequency(mCurrentProgram));
for (const auto& range : mAmFmConfig.ranges) {
if (range.lowerBound <= freq && range.upperBound >= freq) {
- return range;
+ bool isBandChanged = hasBandBefore ? *mCurrentAmFmBandRange != range : true;
+ mCurrentAmFmBandRange = range;
+ return isBandChanged;
}
}
- return {};
+ mCurrentAmFmBandRange.reset();
+ return !hasBandBefore;
}
ScopedAStatus BroadcastRadio::registerAnnouncementListener(
diff --git a/broadcastradio/aidl/default/BroadcastRadio.h b/broadcastradio/aidl/default/BroadcastRadio.h
index 0f818ce..e43d7c5 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.h
+++ b/broadcastradio/aidl/default/BroadcastRadio.h
@@ -39,21 +39,25 @@
public:
explicit BroadcastRadio(const VirtualRadio& virtualRadio);
~BroadcastRadio();
- ndk::ScopedAStatus getAmFmRegionConfig(bool full, AmFmRegionConfig* returnConfigs) override;
+ ndk::ScopedAStatus getAmFmRegionConfig(bool full, AmFmRegionConfig* returnConfigs)
+ EXCLUDES(mMutex) override;
ndk::ScopedAStatus getDabRegionConfig(std::vector<DabTableEntry>* returnConfigs) override;
ndk::ScopedAStatus getImage(int32_t id, std::vector<uint8_t>* returnImage) override;
- ndk::ScopedAStatus getProperties(Properties* returnProperties) override;
+ ndk::ScopedAStatus getProperties(Properties* returnProperties) EXCLUDES(mMutex) override;
- ndk::ScopedAStatus setTunerCallback(const std::shared_ptr<ITunerCallback>& callback) override;
- ndk::ScopedAStatus unsetTunerCallback() override;
- ndk::ScopedAStatus tune(const ProgramSelector& program) override;
- ndk::ScopedAStatus seek(bool directionUp, bool skipSubChannel) override;
- ndk::ScopedAStatus step(bool directionUp) override;
- ndk::ScopedAStatus cancel() override;
- ndk::ScopedAStatus startProgramListUpdates(const ProgramFilter& filter) override;
- ndk::ScopedAStatus stopProgramListUpdates() override;
- ndk::ScopedAStatus isConfigFlagSet(ConfigFlag flag, bool* returnIsSet) override;
- ndk::ScopedAStatus setConfigFlag(ConfigFlag flag, bool in_value) override;
+ ndk::ScopedAStatus setTunerCallback(const std::shared_ptr<ITunerCallback>& callback)
+ EXCLUDES(mMutex) override;
+ ndk::ScopedAStatus unsetTunerCallback() EXCLUDES(mMutex) override;
+ ndk::ScopedAStatus tune(const ProgramSelector& program) EXCLUDES(mMutex) override;
+ ndk::ScopedAStatus seek(bool directionUp, bool skipSubChannel) EXCLUDES(mMutex) override;
+ ndk::ScopedAStatus step(bool directionUp) EXCLUDES(mMutex) override;
+ ndk::ScopedAStatus cancel() EXCLUDES(mMutex) override;
+ ndk::ScopedAStatus startProgramListUpdates(const ProgramFilter& filter)
+ EXCLUDES(mMutex) override;
+ ndk::ScopedAStatus stopProgramListUpdates() EXCLUDES(mMutex) override;
+ ndk::ScopedAStatus isConfigFlagSet(ConfigFlag flag, bool* returnIsSet)
+ EXCLUDES(mMutex) override;
+ ndk::ScopedAStatus setConfigFlag(ConfigFlag flag, bool in_value) EXCLUDES(mMutex) override;
ndk::ScopedAStatus setParameters(const std::vector<VendorKeyValue>& parameters,
std::vector<VendorKeyValue>* returnParameters) override;
ndk::ScopedAStatus getParameters(const std::vector<std::string>& keys,
@@ -62,7 +66,7 @@
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;
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs) EXCLUDES(mMutex) override;
private:
const VirtualRadio& mVirtualRadio;
@@ -75,15 +79,23 @@
bool mIsTuneCompleted GUARDED_BY(mMutex) = true;
Properties mProperties GUARDED_BY(mMutex);
ProgramSelector mCurrentProgram GUARDED_BY(mMutex) = {};
+ std::vector<VirtualProgram> mProgramList GUARDED_BY(mMutex) = {};
+ std::optional<AmFmBandRange> mCurrentAmFmBandRange GUARDED_BY(mMutex);
std::shared_ptr<ITunerCallback> mCallback GUARDED_BY(mMutex);
// Bitmap for all ConfigFlag values
int mConfigFlagValues GUARDED_BY(mMutex) = 0;
- std::optional<AmFmBandRange> getAmFmRangeLocked() const;
- void cancelLocked();
- ProgramInfo tuneInternalLocked(const ProgramSelector& sel);
- void cancelProgramListUpdateLocked();
+ bool adjustAmFmRangeLocked() REQUIRES(mMutex);
+ void cancelLocked() REQUIRES(mMutex);
+ ProgramInfo tuneInternalLocked(const ProgramSelector& sel) REQUIRES(mMutex);
+ void startProgramListUpdatesLocked(const ProgramFilter& filter) REQUIRES(mMutex);
+ void cancelProgramListUpdateLocked() REQUIRES(mMutex);
+ bool findNextLocked(const ProgramSelector& current, bool directionUp, bool skipSubChannel,
+ VirtualProgram* nextProgram) const REQUIRES(mMutex);
+ void jumpToFirstSubChannelLocked(std::vector<VirtualProgram>::const_iterator& it) const
+ REQUIRES(mMutex);
+ bool isConfigFlagSetLocked(ConfigFlag flag) const REQUIRES(mMutex);
binder_status_t cmdHelp(int fd) const;
binder_status_t cmdTune(int fd, const char** args, uint32_t numArgs);
@@ -93,7 +105,7 @@
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);
+ binder_status_t dumpsys(int fd) EXCLUDES(mMutex);
};
} // namespace aidl::android::hardware::broadcastradio
diff --git a/broadcastradio/aidl/default/VirtualProgram.cpp b/broadcastradio/aidl/default/VirtualProgram.cpp
index 4fe6567..19c1dcf 100644
--- a/broadcastradio/aidl/default/VirtualProgram.cpp
+++ b/broadcastradio/aidl/default/VirtualProgram.cpp
@@ -49,7 +49,12 @@
break;
case IdentifierType::HD_STATION_ID_EXT:
info.logicallyTunedTo = selectId(IdentifierType::HD_STATION_ID_EXT);
- info.physicallyTunedTo = selectId(IdentifierType::AMFM_FREQUENCY_KHZ);
+ if (utils::hasId(info.selector, IdentifierType::AMFM_FREQUENCY_KHZ)) {
+ info.physicallyTunedTo = selectId(IdentifierType::AMFM_FREQUENCY_KHZ);
+ } else {
+ info.physicallyTunedTo = utils::makeIdentifier(
+ IdentifierType::AMFM_FREQUENCY_KHZ, utils::getHdFrequency(info.selector));
+ }
break;
case IdentifierType::DAB_SID_EXT:
info.logicallyTunedTo = selectId(IdentifierType::DAB_SID_EXT);
@@ -91,9 +96,34 @@
auto& l = lhs.selector;
auto& r = rhs.selector;
- // Two programs with the same primaryId are considered the same.
- if (l.primaryId.type != r.primaryId.type) return l.primaryId.type < r.primaryId.type;
+ if ((utils::hasId(l, IdentifierType::AMFM_FREQUENCY_KHZ) ||
+ l.primaryId.type == IdentifierType::HD_STATION_ID_EXT) &&
+ (utils::hasId(r, IdentifierType::AMFM_FREQUENCY_KHZ) ||
+ r.primaryId.type == IdentifierType::HD_STATION_ID_EXT)) {
+ uint32_t freq1 = utils::getAmFmFrequency(l);
+ int subChannel1 = l.primaryId.type == IdentifierType::HD_STATION_ID_EXT
+ ? utils::getHdSubchannel(l)
+ : 0;
+ uint32_t freq2 = utils::getAmFmFrequency(r);
+ int subChannel2 = r.primaryId.type == IdentifierType::HD_STATION_ID_EXT
+ ? utils::getHdSubchannel(r)
+ : 0;
+ return freq1 < freq2 || (freq1 == freq2 && (l.primaryId.type < r.primaryId.type ||
+ subChannel1 < subChannel2));
+ } else if (l.primaryId.type == IdentifierType::DAB_SID_EXT &&
+ l.primaryId.type == IdentifierType::DAB_SID_EXT) {
+ uint64_t dabFreq1 = utils::getId(l, IdentifierType::DAB_FREQUENCY_KHZ);
+ uint64_t dabFreq2 = utils::getId(r, IdentifierType::DAB_FREQUENCY_KHZ);
+ if (dabFreq1 != dabFreq2) {
+ return dabFreq1 < dabFreq2;
+ }
+ return utils::getId(l, IdentifierType::DAB_ENSEMBLE) <
+ utils::getId(r, IdentifierType::DAB_ENSEMBLE);
+ }
+ if (l.primaryId.type != r.primaryId.type) {
+ return l.primaryId.type < r.primaryId.type;
+ }
return l.primaryId.value < r.primaryId.value;
}
diff --git a/broadcastradio/aidl/default/VirtualRadio.cpp b/broadcastradio/aidl/default/VirtualRadio.cpp
index 86c5a96..ba43d8a 100644
--- a/broadcastradio/aidl/default/VirtualRadio.cpp
+++ b/broadcastradio/aidl/default/VirtualRadio.cpp
@@ -21,6 +21,7 @@
using ::aidl::android::hardware::broadcastradio::utils::makeSelectorAmfm;
using ::aidl::android::hardware::broadcastradio::utils::makeSelectorDab;
+using ::aidl::android::hardware::broadcastradio::utils::makeSelectorHd;
using ::std::string;
using ::std::vector;
@@ -38,11 +39,25 @@
}
bool VirtualRadio::getProgram(const ProgramSelector& selector, VirtualProgram* programOut) const {
- for (const auto& program : mPrograms) {
- if (utils::tunesTo(selector, program.selector)) {
- *programOut = program;
- return true;
+ for (auto it = mPrograms.begin(); it != mPrograms.end(); it++) {
+ if (!utils::tunesTo(selector, it->selector)) {
+ continue;
}
+ auto firstMatchIt = it;
+ if (utils::hasAmFmFrequency(it->selector)) {
+ uint32_t channelFreq = utils::getAmFmFrequency(it->selector);
+ it++;
+ while (it != mPrograms.end() && utils::hasAmFmFrequency(it->selector) &&
+ utils::getAmFmFrequency(it->selector) == channelFreq) {
+ if (it->selector == selector) {
+ *programOut = *it;
+ return true;
+ }
+ it++;
+ }
+ }
+ *programOut = *firstMatchIt;
+ return true;
}
return false;
}
@@ -56,15 +71,27 @@
{makeSelectorAmfm(/* frequency= */ 94900u), "Wild 94.9", "Drake ft. Rihanna",
"Too Good"},
{makeSelectorAmfm(/* frequency= */ 96500u), "KOIT", "Celine Dion", "All By Myself"},
- {makeSelectorAmfm(/* frequency= */ 97300u), "Alice@97.3", "Drops of Jupiter", "Train"},
- {makeSelectorAmfm(/* frequency= */ 99700u), "99.7 Now!", "The Chainsmokers", "Closer"},
{makeSelectorAmfm(/* frequency= */ 101300u), "101-3 KISS-FM", "Justin Timberlake",
"Rock Your Body"},
{makeSelectorAmfm(/* frequency= */ 103700u), "iHeart80s @ 103.7", "Michael Jackson",
"Billie Jean"},
{makeSelectorAmfm(/* frequency= */ 106100u), "106 KMEL", "Drake", "Marvins Room"},
- {makeSelectorAmfm(/* frequency= */ 700u), "700 AM", "Artist700", "Title700"},
- {makeSelectorAmfm(/* frequency= */ 1700u), "1700 AM", "Artist1700", "Title1700"},
+ {makeSelectorAmfm(/* frequency= */ 560u), "Talk Radio 560 KSFO", "Artist560", "Title560"},
+ {makeSelectorAmfm(/* frequency= */ 680u), "KNBR 680", "Artist680", "Title680"},
+ {makeSelectorAmfm(/* frequency= */ 97300u), "Alice@97.3", "Drops of Jupiter", "Train"},
+ {makeSelectorAmfm(/* frequency= */ 99700u), "99.7 Now!", "The Chainsmokers", "Closer"},
+ {makeSelectorHd(/* stationId= */ 0xA0000001u, /* subChannel= */ 0u, /* frequency= */ 97700u),
+ "K-LOVE", "ArtistHd0", "TitleHd0"},
+ {makeSelectorHd(/* stationId= */ 0xA0000001u, /* subChannel= */ 1u, /* frequency= */ 97700u),
+ "Air1", "ArtistHd1", "TitleHd1"},
+ {makeSelectorHd(/* stationId= */ 0xA0000001u, /* subChannel= */ 2u, /* frequency= */ 97700u),
+ "K-LOVE Classics", "ArtistHd2", "TitleHd2"},
+ {makeSelectorHd(/* stationId= */ 0xA0000001u, /* subChannel= */ 0u, /* frequency= */ 98500u),
+ "98.5-1 South Bay's Classic Rock", "ArtistHd0", "TitleHd0"},
+ {makeSelectorHd(/* stationId= */ 0xA0000001u, /* subChannel= */ 1u, /* frequency= */ 98500u),
+ "Highway 1 - Different", "ArtistHd1", "TitleHd1"},
+ {makeSelectorHd(/* stationId= */ 0xB0000001u, /* subChannel= */ 0u, /* frequency= */ 1170u),
+ "KLOK", "ArtistHd1", "TitleHd1"},
});
// clang-format on
return amFmRadioMock;
diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
index b6fb33f..a139e00 100644
--- a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
+++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h
@@ -139,6 +139,7 @@
ProgramSelector makeSelectorAmfm(uint32_t frequency);
ProgramSelector makeSelectorDab(uint64_t sidExt);
ProgramSelector makeSelectorDab(uint64_t sidExt, uint32_t ensemble, uint64_t freq);
+ProgramSelector makeSelectorHd(uint64_t stationId, uint64_t subChannel, uint64_t frequency);
bool satisfies(const ProgramFilter& filter, const ProgramSelector& sel);
@@ -158,6 +159,14 @@
ProgramIdentifier makeHdRadioStationName(const std::string& name);
+uint32_t getHdFrequency(const ProgramSelector& sel);
+
+int getHdSubchannel(const ProgramSelector& sel);
+
+bool hasAmFmFrequency(const ProgramSelector& sel);
+
+uint32_t getAmFmFrequency(const ProgramSelector& sel);
+
template <typename aidl_type>
inline std::string vectorToString(const std::vector<aidl_type>& in_values) {
return std::accumulate(std::begin(in_values), std::end(in_values), std::string{},
diff --git a/broadcastradio/common/utilsaidl/src/Utils.cpp b/broadcastradio/common/utilsaidl/src/Utils.cpp
index 2875318..4c99514 100644
--- a/broadcastradio/common/utilsaidl/src/Utils.cpp
+++ b/broadcastradio/common/utilsaidl/src/Utils.cpp
@@ -49,12 +49,6 @@
return getId(a, type) == getId(b, type);
}
-int getHdSubchannel(const ProgramSelector& sel) {
- int64_t hdSidExt = getId(sel, IdentifierType::HD_STATION_ID_EXT, /* defaultValue */ 0);
- hdSidExt >>= 32; // Station ID number
- return hdSidExt & 0xF; // HD Radio subchannel
-}
-
bool maybeGetId(const ProgramSelector& sel, const IdentifierType& type, int64_t* val) {
// iterate through primaryId and secondaryIds
for (auto it = begin(sel); it != end(sel); it++) {
@@ -132,8 +126,13 @@
case IdentifierType::AMFM_FREQUENCY_KHZ:
if (haveEqualIds(a, b, IdentifierType::HD_STATION_ID_EXT)) return true;
if (haveEqualIds(a, b, IdentifierType::RDS_PI)) return true;
- return getHdSubchannel(b) == 0 &&
- haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY_KHZ);
+ if (getHdSubchannel(b) != 0) { // supplemental program services
+ return false;
+ }
+ return haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY_KHZ) ||
+ (b.primaryId.type == IdentifierType::HD_STATION_ID_EXT &&
+ static_cast<uint32_t>(getId(a, IdentifierType::AMFM_FREQUENCY_KHZ)) ==
+ getAmFmFrequency(b));
case IdentifierType::DAB_SID_EXT:
if (!haveEqualIds(a, b, IdentifierType::DAB_SID_EXT)) {
return false;
@@ -316,6 +315,13 @@
return sel;
}
+ProgramSelector makeSelectorHd(uint64_t stationId, uint64_t subChannel, uint64_t frequency) {
+ ProgramSelector sel = {};
+ uint64_t sidExt = stationId | (subChannel << 32) | (frequency << 36);
+ sel.primaryId = makeIdentifier(IdentifierType::HD_STATION_ID_EXT, sidExt);
+ return sel;
+}
+
ProgramSelector makeSelectorDab(uint64_t sidExt, uint32_t ensemble, uint64_t freq) {
ProgramSelector sel = {};
sel.primaryId = makeIdentifier(IdentifierType::DAB_SID_EXT, sidExt);
@@ -483,6 +489,32 @@
return static_cast<IdentifierType>(typeAsInt);
}
+int getHdSubchannel(const ProgramSelector& sel) {
+ int64_t hdSidExt = getId(sel, IdentifierType::HD_STATION_ID_EXT, kValueForNotFoundIdentifier);
+ hdSidExt >>= 32; // Station ID number
+ return hdSidExt & 0xF; // HD Radio subchannel
+}
+
+uint32_t getHdFrequency(const ProgramSelector& sel) {
+ int64_t hdSidExt = getId(sel, IdentifierType::HD_STATION_ID_EXT, kValueForNotFoundIdentifier);
+ if (hdSidExt == kValueForNotFoundIdentifier) {
+ return kValueForNotFoundIdentifier;
+ }
+ return static_cast<uint32_t>((hdSidExt >> 36) & 0x3FFFF); // HD Radio subchannel
+}
+
+bool hasAmFmFrequency(const ProgramSelector& sel) {
+ return hasId(sel, IdentifierType::AMFM_FREQUENCY_KHZ) ||
+ sel.primaryId.type == IdentifierType::HD_STATION_ID_EXT;
+}
+
+uint32_t getAmFmFrequency(const ProgramSelector& sel) {
+ if (hasId(sel, IdentifierType::AMFM_FREQUENCY_KHZ)) {
+ return static_cast<uint32_t>(getId(sel, IdentifierType::AMFM_FREQUENCY_KHZ));
+ }
+ return getHdFrequency(sel);
+}
+
bool parseArgInt(const std::string& s, int* out) {
return ::android::base::ParseInt(s, out);
}
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index aaafe7f..8a22d6e 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -217,6 +217,10 @@
* Starts a location output stream using the IGnssCallback gnssLocationCb(), following the
* settings from the most recent call to setPositionMode().
*
+ * When a location output stream is in progress, calling setPositionMode() does not change the
+ * settings of the current location output stream. stop() and start() must be called to make the
+ * new settings effective.
+ *
* This output must operate independently of any GNSS location batching operations,
* see the IGnssBatching for details.
*/
@@ -306,6 +310,10 @@
/**
* Sets the GnssPositionMode parameter, its associated recurrence value, the time between fixes,
* requested fix accuracy, time to first fix.
+ *
+ * If a location output stream is in progress, calling this method does not affect the settings
+ * of current location output stream. stop() and start() must be called to make the new settings
+ * effective.
*/
void setPositionMode(in PositionModeOptions options);
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
index 3e460dd..e13ba1f 100644
--- a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -39,7 +39,7 @@
ParcelFileDescriptor getWaitableFd();
parcelable Allocation {
android.hardware.HardwareBuffer buffer;
- ParcelFileDescriptor fence;
+ @nullable ParcelFileDescriptor fence;
}
parcelable Description {
int width;
diff --git a/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
index 49c4ea4..1710242 100644
--- a/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -35,7 +35,7 @@
*/
parcelable Allocation {
HardwareBuffer buffer;
- ParcelFileDescriptor fence;
+ @nullable ParcelFileDescriptor fence;
}
/**
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NasProtocolMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NasProtocolMessage.aidl
index 9f852cc..4fbc802 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NasProtocolMessage.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NasProtocolMessage.aidl
@@ -44,4 +44,7 @@
AUTHENTICATION_AND_CIPHERING_RESPONSE = 6,
REGISTRATION_REQUEST = 7,
DEREGISTRATION_REQUEST = 8,
+ CM_REESTABLISHMENT_REQUEST = 9,
+ CM_SERVICE_REQUEST = 10,
+ IMSI_DETACH_INDICATION = 11,
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 32890ec..e2df8dd 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -669,7 +669,7 @@
* Note: Cellular identifiers disclosed in uplink messages covered under a NAS Security Context
* as well as identifiers disclosed in downlink messages are out of scope.
*
- * This feature applies to 2g, 3g, 4g, and 5g (SA and NSA) messages sent before a NAS security
+ * This feature applies to 2g, 3g, 4g, and 5g (SA and NSA) messages sent before a security
* context is established. In scope message definitions and their associated spec references can
* be found in NasProtocolMessage.
*
@@ -678,8 +678,6 @@
* re-enables this functionality. The modem may choose to stop tracking cellular identifiers in
* the clear during this time.
*
- * Note: The default value of enabled shall be true.
- *
* @param serial Serial number of request
* @param enabled Whether or not to enable sending indications for cellular identifiers in the
* clear
@@ -694,8 +692,6 @@
* Enables or disables security algorithm update reports via indication API
* {@link IRadioNetworkIndication.securityAlgorithmsUpdated()}.
*
- * Note: The default value shall be enabled.
- *
* @param serial Serial number of request.
* @param enable {@code true} to enable security algorithm update reports, {@code false} to
* disable.
diff --git a/radio/aidl/android/hardware/radio/network/NasProtocolMessage.aidl b/radio/aidl/android/hardware/radio/network/NasProtocolMessage.aidl
index e8d8047..1225c41 100644
--- a/radio/aidl/android/hardware/radio/network/NasProtocolMessage.aidl
+++ b/radio/aidl/android/hardware/radio/network/NasProtocolMessage.aidl
@@ -54,5 +54,14 @@
REGISTRATION_REQUEST = 7,
// Reference: 3GPP TS 24.501 8.2.12
// Applies to 5g networks
- DEREGISTRATION_REQUEST = 8
+ DEREGISTRATION_REQUEST = 8,
+ // Reference: 3GPP TS 24.008 9.2.4
+ // Applies to 2g and 3g networks
+ CM_REESTABLISHMENT_REQUEST = 9,
+ // Reference: 3GPP TS 24.008 9.2.9
+ // Applies to 2g and 3g networks
+ CM_SERVICE_REQUEST = 10,
+ // Reference: 3GPP TS 24.008 9.2.14
+ // Applies to 2g and 3g networks. Used for circuit-switched detach.
+ IMSI_DETACH_INDICATION = 11
}
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index c893553..98422af 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -2433,10 +2433,6 @@
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_network->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
-
- // the default value should be true if we have not called the setter
- EXPECT_TRUE(radioRsp_network->isCellularIdentifierTransparencyEnabled);
-
}
TEST_P(RadioNetworkTest, setCellularIdentifierTransparencyEnabled) {
@@ -2567,7 +2563,4 @@
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_network->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
-
- // the default value should be true if we have not called the setter
- EXPECT_TRUE(radioRsp_network->isSecurityAlgorithmsUpdatedEnabled);
}
diff --git a/security/authgraph/aidl/vts/functional/Android.bp b/security/authgraph/aidl/vts/functional/Android.bp
index 0e3480f..28a70e2 100644
--- a/security/authgraph/aidl/vts/functional/Android.bp
+++ b/security/authgraph/aidl/vts/functional/Android.bp
@@ -50,6 +50,7 @@
rust_test {
name: "VtsAidlAuthGraphRoleTest",
srcs: ["role_test.rs"],
+ require_root: true,
test_suites: [
"general-tests",
"vts",
diff --git a/security/authgraph/aidl/vts/functional/role_test.rs b/security/authgraph/aidl/vts/functional/role_test.rs
index 71a2fae..3075d8a 100644
--- a/security/authgraph/aidl/vts/functional/role_test.rs
+++ b/security/authgraph/aidl/vts/functional/role_test.rs
@@ -22,13 +22,18 @@
use android_hardware_security_authgraph::aidl::android::hardware::security::authgraph::{
IAuthGraphKeyExchange::IAuthGraphKeyExchange,
};
+use binder::StatusCode;
const AUTH_GRAPH_NONSECURE: &str =
"android.hardware.security.authgraph.IAuthGraphKeyExchange/nonsecure";
/// Retrieve the /nonsecure instance of AuthGraph, which supports both sink and source roles.
fn get_nonsecure() -> Option<binder::Strong<dyn IAuthGraphKeyExchange>> {
- binder::get_interface(AUTH_GRAPH_NONSECURE).ok()
+ match binder::get_interface(AUTH_GRAPH_NONSECURE) {
+ Ok(ag) => Some(ag),
+ Err(StatusCode::NAME_NOT_FOUND) => None,
+ Err(e) => panic!("failed to get AuthGraph/nonsecure: {e:?}"),
+ }
}
/// Macro to require availability of a /nonsecure instance of AuthGraph.
diff --git a/security/authgraph/aidl/vts/functional/source.rs b/security/authgraph/aidl/vts/functional/source.rs
index 4178a99..a1e76b3 100644
--- a/security/authgraph/aidl/vts/functional/source.rs
+++ b/security/authgraph/aidl/vts/functional/source.rs
@@ -250,9 +250,13 @@
&corrupt_key,
);
- let err = result.expect_err("expect failure with corrupt signature");
- assert_eq!(
- err,
- binder::Status::new_service_specific_error(Error::INVALID_PRIV_KEY_ARC_IN_KEY.0, None)
+ let err = result.expect_err("expect failure with corrupt key");
+ assert!(
+ err == binder::Status::new_service_specific_error(Error::INVALID_KE_KEY.0, None)
+ || err
+ == binder::Status::new_service_specific_error(
+ Error::INVALID_PRIV_KEY_ARC_IN_KEY.0,
+ None
+ )
);
}
diff --git a/security/authgraph/default/Android.bp b/security/authgraph/default/Android.bp
index c481075..7894477 100644
--- a/security/authgraph/default/Android.bp
+++ b/security/authgraph/default/Android.bp
@@ -46,11 +46,11 @@
name: "android.hardware.security.authgraph-service.nonsecure",
relative_install_path: "hw",
vendor: true,
- init_rc: ["authgraph.rc"],
- vintf_fragments: ["authgraph.xml"],
+ installable: false, // install com.android.hardware.security.authgraph
defaults: [
"authgraph_use_latest_hal_aidl_rust",
],
+ prefer_rlib: true,
rustlibs: [
"libandroid_logger",
"libauthgraph_hal",
@@ -80,3 +80,34 @@
],
},
}
+
+prebuilt_etc {
+ name: "authgraph.xml",
+ src: "authgraph.xml",
+ sub_dir: "vintf",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "authgraph.rc",
+ src: "authgraph.rc",
+ installable: false,
+}
+
+apex {
+ name: "com.android.hardware.security.authgraph",
+ manifest: "apex_manifest.json",
+ file_contexts: "apex_file_contexts",
+ key: "com.android.hardware.key",
+ certificate: ":com.android.hardware.certificate",
+ vendor: true,
+ updatable: false,
+
+ binaries: [
+ "android.hardware.security.authgraph-service.nonsecure",
+ ],
+ prebuilts: [
+ "authgraph.rc",
+ "authgraph.xml",
+ ],
+}
diff --git a/security/authgraph/default/apex_file_contexts b/security/authgraph/default/apex_file_contexts
new file mode 100644
index 0000000..9a54613
--- /dev/null
+++ b/security/authgraph/default/apex_file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.security\.authgraph-service\.nonsecure u:object_r:hal_authgraph_default_exec:s0
diff --git a/security/authgraph/default/apex_manifest.json b/security/authgraph/default/apex_manifest.json
new file mode 100644
index 0000000..0723846
--- /dev/null
+++ b/security/authgraph/default/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.security.authgraph",
+ "version": 1
+}
\ No newline at end of file
diff --git a/security/authgraph/default/authgraph.rc b/security/authgraph/default/authgraph.rc
index 0222994..2d07542 100644
--- a/security/authgraph/default/authgraph.rc
+++ b/security/authgraph/default/authgraph.rc
@@ -1,4 +1,4 @@
-service vendor.authgraph /vendor/bin/hw/android.hardware.security.authgraph-service.nonsecure
+service vendor.authgraph /apex/com.android.hardware.security.authgraph/bin/hw/android.hardware.security.authgraph-service.nonsecure
interface aidl android.hardware.security.authgraph.IAuthGraph/nonsecure
class hal
user nobody
diff --git a/security/authgraph/default/src/lib.rs b/security/authgraph/default/src/lib.rs
index 43d037c..14741aa 100644
--- a/security/authgraph/default/src/lib.rs
+++ b/security/authgraph/default/src/lib.rs
@@ -18,38 +18,11 @@
use authgraph_boringssl as boring;
use authgraph_core::{
- error,
- key::MillisecondsSinceEpoch,
- keyexchange,
+ error, keyexchange,
ta::{AuthGraphTa, Role},
- traits,
};
use authgraph_hal::channel::SerializedChannel;
use std::sync::{Arc, Mutex};
-use std::time::Instant;
-
-/// Monotonic clock with an epoch that starts at the point of construction.
-/// (This makes it unsuitable for use outside of testing, because the epoch
-/// will not match that of any other component.)
-pub struct StdClock(Instant);
-
-impl Default for StdClock {
- fn default() -> Self {
- Self(Instant::now())
- }
-}
-
-impl traits::MonotonicClock for StdClock {
- fn now(&self) -> MillisecondsSinceEpoch {
- let millis: i64 = self
- .0
- .elapsed()
- .as_millis()
- .try_into()
- .expect("failed to fit timestamp in i64");
- MillisecondsSinceEpoch(millis)
- }
-}
/// Implementation of the AuthGraph TA that runs locally in-process (and which is therefore
/// insecure).
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 34f7ce4..6edbfc1 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -520,6 +520,15 @@
std::to_string(info.versionNumber) + ").";
}
}
+ // Bypasses the device info validation since the device info in AVF is currently
+ // empty. Check b/299256925 for more information.
+ //
+ // TODO(b/300911665): This check is temporary and will be replaced once the markers
+ // on the DICE chain become available. We need to determine if the CSR is from the
+ // RKP VM using the markers on the DICE chain.
+ if (info.uniqueId == "AVF Remote Provisioning 1") {
+ return std::move(parsed);
+ }
std::string error;
std::string tmp;
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 62463eb..a1de93e 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -55,6 +55,8 @@
constexpr uint8_t MIN_CHALLENGE_SIZE = 0;
constexpr uint8_t MAX_CHALLENGE_SIZE = 64;
+const string RKP_VM_INSTANCE_NAME =
+ "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf";
#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
@@ -181,7 +183,12 @@
provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
}
ASSERT_NE(provisionable_, nullptr);
- ASSERT_TRUE(provisionable_->getHardwareInfo(&rpcHardwareInfo).isOk());
+ auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo);
+ if (GetParam() == RKP_VM_INSTANCE_NAME &&
+ status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "The RKP VM is not supported on this system.";
+ }
+ ASSERT_TRUE(status.isOk());
}
static vector<string> build_params() {
@@ -207,7 +214,11 @@
ASSERT_NE(rpc, nullptr);
RpcHardwareInfo hwInfo;
- ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
+ auto status = rpc->getHardwareInfo(&hwInfo);
+ if (hal == RKP_VM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "The RKP VM is not supported on this system.";
+ }
+ ASSERT_TRUE(status.isOk());
if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
ASSERT_TRUE(hwInfo.uniqueId);
diff --git a/threadnetwork/aidl/Android.bp b/threadnetwork/aidl/Android.bp
index c621b81..7e674e0 100644
--- a/threadnetwork/aidl/Android.bp
+++ b/threadnetwork/aidl/Android.bp
@@ -15,9 +15,6 @@
apex_available: [
"//apex_available:platform",
"com.android.tethering",
- // Keep the threadnetwork apex to make it buildable on udc-mainline-prod.
- // TODO: remove it after moving ot-daemon into tethering.
- "com.android.threadnetwork",
],
min_sdk_version: "30",
},
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl
index ca20f37..1a66105 100644
--- a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl
@@ -40,4 +40,5 @@
android.hardware.wifi.hostapd.ChannelBandwidth channelBandwidth;
android.hardware.wifi.hostapd.Generation generation;
byte[] apIfaceInstanceMacAddress;
+ @nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl
index a6fe63b..f2b2ee6 100644
--- a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl
@@ -16,6 +16,7 @@
package android.hardware.wifi.hostapd;
+import android.hardware.wifi.common.OuiKeyedData;
import android.hardware.wifi.hostapd.ChannelBandwidth;
import android.hardware.wifi.hostapd.Generation;
@@ -57,4 +58,9 @@
* MAC Address of the apIfaceInstance.
*/
byte[] apIfaceInstanceMacAddress;
+
+ /**
+ * Optional vendor-specific information.
+ */
+ @nullable OuiKeyedData[] vendorData;
}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
index 1616b26..1f3aa48 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -54,6 +54,9 @@
android.hardware.wifi.supplicant.IfaceType getType();
android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask getWpaDriverCapabilities();
void initiateAnqpQuery(in byte[] macAddress, in android.hardware.wifi.supplicant.AnqpInfoId[] infoElements, in android.hardware.wifi.supplicant.Hs20AnqpSubtypes[] subTypes);
+ /**
+ * @deprecated No longer in use.
+ */
void initiateHs20IconQuery(in byte[] macAddress, in String fileName);
void initiateTdlsDiscover(in byte[] macAddress);
void initiateTdlsSetup(in byte[] macAddress);
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 1c23223..898c2d4 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -53,6 +53,9 @@
oneway void onExtRadioWorkStart(in int id);
oneway void onExtRadioWorkTimeout(in int id);
oneway void onHs20DeauthImminentNotice(in byte[] bssid, in int reasonCode, in int reAuthDelayInSec, in String url);
+ /**
+ * @deprecated No longer in use.
+ */
oneway void onHs20IconQueryDone(in byte[] bssid, in String fileName, in byte[] data);
oneway void onHs20SubscriptionRemediation(in byte[] bssid, in android.hardware.wifi.supplicant.OsuMethod osuMethod, in String url);
oneway void onHs20TermsAndConditionsAcceptanceRequestedNotification(in byte[] bssid, in String url);
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
index 06ab8fb..d7b4e62 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -304,6 +304,8 @@
* The icon data fetched must be returned in the
* |ISupplicantStaIfaceCallback.onHs20IconQueryDone| callback.
*
+ * @deprecated No longer in use.
+ *
* @param macAddress MAC address of the access point.
* @param fileName Name of the file to request from the access point.
* @throws ServiceSpecificException with one of the following values:
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 17a220d..58893eb 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -198,6 +198,8 @@
/**
* Used to indicate the result of Hotspot 2.0 Icon query.
*
+ * @deprecated No longer in use.
+ *
* @param bssid BSSID of the access point.
* @param fileName Name of the file that was requested.
* @param data Icon data fetched from the access point.