Merge "camera: Add device info version"
diff --git a/broadcastradio/2.0/Android.bp b/broadcastradio/2.0/Android.bp
index 1d7861e..7409005 100644
--- a/broadcastradio/2.0/Android.bp
+++ b/broadcastradio/2.0/Android.bp
@@ -8,7 +8,9 @@
},
srcs: [
"types.hal",
+ "IAnnouncementObserver.hal",
"IBroadcastRadio.hal",
+ "ICloseHandle.hal",
"ITunerCallback.hal",
"ITunerSession.hal",
],
@@ -16,8 +18,14 @@
"android.hidl.base@1.0",
],
types: [
+ "AmFmBandRange",
+ "AmFmRegionConfig",
+ "Announcement",
+ "AnnouncementType",
"ConfigFlag",
"Constants",
+ "DabTableEntry",
+ "Deemphasis",
"IdentifierType",
"Metadata",
"MetadataKey",
@@ -28,6 +36,7 @@
"ProgramListChunk",
"ProgramSelector",
"Properties",
+ "Rds",
"Result",
"VendorKeyValue",
],
diff --git a/broadcastradio/2.0/IAnnouncementObserver.hal b/broadcastradio/2.0/IAnnouncementObserver.hal
new file mode 100644
index 0000000..c91e29a
--- /dev/null
+++ b/broadcastradio/2.0/IAnnouncementObserver.hal
@@ -0,0 +1,30 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio@2.0;
+
+/**
+ * Callback interface for announcement observer.
+ *
+ * For typical configuration, the observer is a broadcast radio service.
+ */
+interface IAnnouncementObserver {
+ /**
+ * Called whenever announcement list has changed.
+ *
+ * @param announcements The complete list of currently active announcements.
+ */
+ oneway onListUpdated(vec<Announcement> announcements);
+};
diff --git a/broadcastradio/2.0/IBroadcastRadio.hal b/broadcastradio/2.0/IBroadcastRadio.hal
index 3ab1cc2..7578f44 100644
--- a/broadcastradio/2.0/IBroadcastRadio.hal
+++ b/broadcastradio/2.0/IBroadcastRadio.hal
@@ -15,6 +15,8 @@
package android.hardware.broadcastradio@2.0;
+import IAnnouncementObserver;
+import ICloseHandle;
import ITunerCallback;
import ITunerSession;
@@ -33,6 +35,28 @@
getProperties() generates (Properties properties);
/**
+ * Fetches current or possible AM/FM region configuration.
+ *
+ * @param full If true, returns full hardware capabilities.
+ * If false, returns current regional configuration.
+ * @return result OK in case of success.
+ * NOT_SUPPORTED if the tuner doesn't support AM/FM.
+ * @return config Hardware capabilities (full=true) or
+ * current configuration (full=false).
+ */
+ getAmFmRegionConfig(bool full)
+ generates (Result result, AmFmRegionConfig config);
+
+ /**
+ * Fetches current DAB region configuration.
+ *
+ * @return result OK in case of success.
+ * NOT_SUPPORTED if the tuner doesn't support DAB.
+ * @return config Current configuration.
+ */
+ getDabRegionConfig() generates (Result result, vec<DabTableEntry> config);
+
+ /**
* Opens a new tuner session.
*
* There may be only one session active at a time. If the new session was
@@ -44,7 +68,7 @@
* @return session The session interface.
*/
openSession(ITunerCallback callback)
- generates (Result result, ITunerSession session);
+ generates (Result result, ITunerSession session);
/**
* Fetch image from radio module cache.
@@ -78,4 +102,28 @@
* or a zero-length vector if identifier doesn't exist.
*/
getImage(uint32_t id) generates (vec<uint8_t> image);
+
+ /**
+ * Registers announcement observer.
+ *
+ * If there is at least one observer registered, HAL implementation must
+ * notify about announcements even if no sessions are active.
+ *
+ * If the observer dies, the HAL implementation must unregister observer
+ * automatically.
+ *
+ * @param enabled The list of announcement types to watch for.
+ * @param cb The callback interface.
+ * @return result OK in case of success.
+ * NOT_SUPPORTED if the tuner doesn't support announcements.
+ * @return closeHandle A handle to unregister observer,
+ * nullptr if result was not OK.
+ */
+ registerAnnouncementObserver(
+ vec<AnnouncementType> enabled,
+ IAnnouncementObserver cb
+ ) generates (
+ Result result,
+ ICloseHandle closeHandle
+ );
};
diff --git a/broadcastradio/2.0/ICloseHandle.hal b/broadcastradio/2.0/ICloseHandle.hal
new file mode 100644
index 0000000..34cea14
--- /dev/null
+++ b/broadcastradio/2.0/ICloseHandle.hal
@@ -0,0 +1,32 @@
+/* Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.broadcastradio@2.0;
+
+/**
+ * Represents a generic close handle to remove a callback that doesn't need
+ * active interface.
+ */
+interface ICloseHandle {
+ /**
+ * Closes the handle.
+ *
+ * The call must not fail and must only be issued once.
+ *
+ * After the close call is executed, no other calls to this interface
+ * are allowed.
+ */
+ close();
+};
diff --git a/broadcastradio/2.0/ITunerSession.hal b/broadcastradio/2.0/ITunerSession.hal
index a3f93fd..a58fa62 100644
--- a/broadcastradio/2.0/ITunerSession.hal
+++ b/broadcastradio/2.0/ITunerSession.hal
@@ -154,7 +154,7 @@
* @return results Operation completion status for parameters being set.
*/
setParameters(vec<VendorKeyValue> parameters)
- generates (vec<VendorKeyValue> results);
+ generates (vec<VendorKeyValue> results);
/**
* Generic method for retrieving vendor-specific parameter values.
diff --git a/broadcastradio/2.0/default/Android.bp b/broadcastradio/2.0/default/Android.bp
index 6d4effb..900454e 100644
--- a/broadcastradio/2.0/default/Android.bp
+++ b/broadcastradio/2.0/default/Android.bp
@@ -24,6 +24,9 @@
"-Wextra",
"-Werror",
],
+ cppflags: [
+ "-std=c++1z",
+ ],
srcs: [
"BroadcastRadio.cpp",
"TunerSession.cpp",
diff --git a/broadcastradio/2.0/default/BroadcastRadio.cpp b/broadcastradio/2.0/default/BroadcastRadio.cpp
index 5ab517d..d16aaff 100644
--- a/broadcastradio/2.0/default/BroadcastRadio.cpp
+++ b/broadcastradio/2.0/default/BroadcastRadio.cpp
@@ -33,6 +33,16 @@
using std::mutex;
using std::vector;
+static const AmFmRegionConfig gDefaultAmFmConfig = { //
+ {
+ {87500, 108000, 100, 100}, // FM
+ {153, 282, 3, 9}, // AM LW
+ {531, 1620, 9, 9}, // AM MW
+ {1600, 30000, 1, 5}, // AM SW
+ },
+ static_cast<uint32_t>(Deemphasis::D50),
+ static_cast<uint32_t>(Rds::RDS)};
+
static Properties initProperties(const VirtualRadio& virtualRadio) {
Properties prop = {};
@@ -51,7 +61,9 @@
}
BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio)
- : mVirtualRadio(virtualRadio), mProperties(initProperties(virtualRadio)) {}
+ : mVirtualRadio(virtualRadio),
+ mProperties(initProperties(virtualRadio)),
+ mAmFmConfig(gDefaultAmFmConfig) {}
Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
ALOGV("%s", __func__);
@@ -59,6 +71,44 @@
return {};
}
+AmFmRegionConfig BroadcastRadio::getAmFmConfig() const {
+ lock_guard<mutex> lk(mMut);
+ return mAmFmConfig;
+}
+
+Return<void> BroadcastRadio::getAmFmRegionConfig(bool full, getAmFmRegionConfig_cb _hidl_cb) {
+ ALOGV("%s(%d)", __func__, full);
+
+ if (full) {
+ AmFmRegionConfig config = {};
+ config.ranges = hidl_vec<AmFmBandRange>({
+ {65000, 108000, 10, 0}, // FM
+ {150, 30000, 1, 0}, // AM
+ });
+ config.fmDeemphasis = Deemphasis::D50 | Deemphasis::D75;
+ config.fmRds = Rds::RDS | Rds::RBDS;
+ _hidl_cb(Result::OK, config);
+ return {};
+ } else {
+ _hidl_cb(Result::OK, getAmFmConfig());
+ return {};
+ }
+}
+
+Return<void> BroadcastRadio::getDabRegionConfig(getDabRegionConfig_cb _hidl_cb) {
+ ALOGV("%s", __func__);
+
+ hidl_vec<DabTableEntry> config = {
+ {"5A", 174928}, {"7D", 194064}, {"8A", 195936}, {"8B", 197648}, {"9A", 202928},
+ {"9B", 204640}, {"9C", 206352}, {"10B", 211648}, {"10C", 213360}, {"10D", 215072},
+ {"11A", 216928}, {"11B", 218640}, {"11C", 220352}, {"11D", 222064}, {"12A", 223936},
+ {"12B", 225648}, {"12C", 227360}, {"12D", 229072},
+ };
+
+ _hidl_cb(Result::OK, config);
+ return {};
+}
+
Return<void> BroadcastRadio::openSession(const sp<ITunerCallback>& callback,
openSession_cb _hidl_cb) {
ALOGV("%s", __func__);
@@ -91,6 +141,15 @@
return {};
}
+Return<void> BroadcastRadio::registerAnnouncementObserver(
+ const hidl_vec<AnnouncementType>& enabled, const sp<IAnnouncementObserver>& /* cb */,
+ registerAnnouncementObserver_cb _hidl_cb) {
+ ALOGV("%s(%s)", __func__, toString(enabled).c_str());
+
+ _hidl_cb(Result::NOT_SUPPORTED, nullptr);
+ return {};
+}
+
} // namespace implementation
} // namespace V2_0
} // namespace broadcastradio
diff --git a/broadcastradio/2.0/default/BroadcastRadio.h b/broadcastradio/2.0/default/BroadcastRadio.h
index fcf0615..7904946 100644
--- a/broadcastradio/2.0/default/BroadcastRadio.h
+++ b/broadcastradio/2.0/default/BroadcastRadio.h
@@ -32,14 +32,22 @@
// V2_0::IBroadcastRadio methods
Return<void> getProperties(getProperties_cb _hidl_cb) override;
+ Return<void> getAmFmRegionConfig(bool full, getAmFmRegionConfig_cb _hidl_cb);
+ Return<void> getDabRegionConfig(getDabRegionConfig_cb _hidl_cb);
Return<void> openSession(const sp<ITunerCallback>& callback, openSession_cb _hidl_cb) override;
Return<void> getImage(uint32_t id, getImage_cb _hidl_cb);
+ Return<void> registerAnnouncementObserver(const hidl_vec<AnnouncementType>& enabled,
+ const sp<IAnnouncementObserver>& cb,
+ registerAnnouncementObserver_cb _hidl_cb);
std::reference_wrapper<const VirtualRadio> mVirtualRadio;
Properties mProperties;
+ AmFmRegionConfig getAmFmConfig() const;
+
private:
- std::mutex mMut;
+ mutable std::mutex mMut;
+ AmFmRegionConfig mAmFmConfig;
wp<TunerSession> mSession;
};
diff --git a/broadcastradio/2.0/default/TunerSession.cpp b/broadcastradio/2.0/default/TunerSession.cpp
index 244544a..3166d86 100644
--- a/broadcastradio/2.0/default/TunerSession.cpp
+++ b/broadcastradio/2.0/default/TunerSession.cpp
@@ -77,8 +77,12 @@
mCallback->onCurrentProgramInfoChanged(programInfo);
}
+const BroadcastRadio& TunerSession::module() const {
+ return mModule.get();
+}
+
const VirtualRadio& TunerSession::virtualRadio() const {
- return mModule.get().mVirtualRadio;
+ return module().mVirtualRadio;
}
Return<Result> TunerSession::tune(const ProgramSelector& sel) {
@@ -86,7 +90,7 @@
lock_guard<mutex> lk(mMut);
if (mIsClosed) return Result::INVALID_STATE;
- if (!utils::isSupported(mModule.get().mProperties, sel)) {
+ if (!utils::isSupported(module().mProperties, sel)) {
ALOGW("Selector not supported");
return Result::NOT_SUPPORTED;
}
@@ -170,23 +174,19 @@
mIsTuneCompleted = false;
auto stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
-#if 0
- // TODO(b/69958423): handle regions
- if (directionUp) {
- stepTo += mAmfmConfig.spacings[0];
- } else {
- stepTo -= mAmfmConfig.spacings[0];
+ auto range = getAmFmRangeLocked();
+ if (!range) {
+ ALOGE("Can't find current band");
+ return Result::INTERNAL_ERROR;
}
- if (stepTo > mAmfmConfig.upperLimit) stepTo = mAmfmConfig.lowerLimit;
- if (stepTo < mAmfmConfig.lowerLimit) stepTo = mAmfmConfig.upperLimit;
-#else
if (directionUp) {
- stepTo += 100;
+ stepTo += range->spacing;
} else {
- stepTo -= 100;
+ stepTo -= range->spacing;
}
-#endif
+ if (stepTo > range->upperBound) stepTo = range->lowerBound;
+ if (stepTo < range->lowerBound) stepTo = range->upperBound;
auto task = [this, stepTo]() {
ALOGI("Performing step to %s", std::to_string(stepTo).c_str());
@@ -280,6 +280,18 @@
return {};
}
+std::optional<AmFmBandRange> TunerSession::getAmFmRangeLocked() const {
+ if (!mIsTuneCompleted) return {};
+ if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) return {};
+
+ auto freq = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
+ for (auto&& range : module().getAmFmConfig().ranges) {
+ if (range.lowerBound <= freq && range.upperBound >= freq) return range;
+ }
+
+ return {};
+}
+
} // namespace implementation
} // namespace V2_0
} // namespace broadcastradio
diff --git a/broadcastradio/2.0/default/TunerSession.h b/broadcastradio/2.0/default/TunerSession.h
index a58aa19..5d27b1e 100644
--- a/broadcastradio/2.0/default/TunerSession.h
+++ b/broadcastradio/2.0/default/TunerSession.h
@@ -22,6 +22,8 @@
#include <android/hardware/broadcastradio/2.0/ITunerSession.h>
#include <broadcastradio-utils/WorkerThread.h>
+#include <optional>
+
namespace android {
namespace hardware {
namespace broadcastradio {
@@ -48,6 +50,8 @@
getParameters_cb _hidl_cb) override;
virtual Return<void> close() override;
+ std::optional<AmFmBandRange> getAmFmRangeLocked() const;
+
private:
std::mutex mMut;
WorkerThread mThread;
@@ -61,6 +65,7 @@
void tuneInternalLocked(const ProgramSelector& sel);
const VirtualRadio& virtualRadio() const;
+ const BroadcastRadio& module() const;
};
} // namespace implementation
diff --git a/broadcastradio/2.0/types.hal b/broadcastradio/2.0/types.hal
index b5264f4..c5880e2 100644
--- a/broadcastradio/2.0/types.hal
+++ b/broadcastradio/2.0/types.hal
@@ -32,6 +32,7 @@
enum Result : int32_t {
OK,
UNKNOWN_ERROR,
+ INTERNAL_ERROR,
INVALID_ARGUMENTS,
INVALID_STATE,
NOT_SUPPORTED,
@@ -120,6 +121,108 @@
};
/**
+ * A supported or configured RDS variant.
+ *
+ * Both might be set for hardware capabilities check (with full=true when
+ * calling getAmFmRegionConfig), but only one (or none) for specific
+ * region settings.
+ */
+enum Rds : uint8_t {
+ /** Standard variant, used everywhere except North America. */
+ RDS = 1 << 0,
+
+ /** Variant used in North America. */
+ RBDS = 1 << 1,
+};
+
+/**
+ * FM de-emphasis filter supported or configured.
+ *
+ * Both might be set for hardware capabilities check (with full=true when
+ * calling getAmFmRegionConfig), but exactly one for specific region settings.
+ */
+enum Deemphasis : uint8_t {
+ D50 = 1 << 0,
+ D75 = 1 << 1,
+};
+
+/**
+ * Regional configuration for AM/FM.
+ *
+ * For hardware capabilities check (with full=true when calling
+ * getAmFmRegionConfig), HAL implementation fills entire supported range of
+ * frequencies and features.
+ *
+ * When checking current configuration, at most one bit in each bitfield
+ * can be set.
+ */
+struct AmFmRegionConfig {
+ /**
+ * All supported or configured AM/FM bands.
+ *
+ * AM/FM bands are identified by frequency value
+ * (see IdentifierType::AMFM_FREQUENCY).
+ *
+ * With typical configuration, it's expected to have two frequency ranges
+ * for capabilities check (AM and FM) and four ranges for specific region
+ * configuration (AM LW, AM MW, AM SW, FM).
+ */
+ vec<AmFmBandRange> ranges;
+
+ /** De-emphasis filter supported/configured. */
+ bitfield<Deemphasis> fmDeemphasis;
+
+ /** RDS/RBDS variant supported/configured. */
+ bitfield<Rds> fmRds;
+};
+
+/**
+ * AM/FM band range for region configuration.
+ *
+ * Defines channel grid: each possible channel is set at
+ * lowerBound + channelNumber * spacing, up to upperBound.
+ */
+struct AmFmBandRange {
+ /** The frequency of the first channel within the range. */
+ uint32_t lowerBound;
+
+ /** The frequency of the last channel within the range. */
+ uint32_t upperBound;
+
+ /** Channel grid resolution, how far apart are the channels. */
+ uint32_t spacing;
+
+ /**
+ * Spacing used when scanning for channels. It's a multiply of spacing and
+ * allows to skip some channels when scanning to make it faster.
+ *
+ * Tuner may first quickly check every n-th channel and if it detects echo
+ * from a station, it fine-tunes to find the exact frequency.
+ *
+ * It's ignored for capabilities check (with full=true when calling
+ * getAmFmRegionConfig).
+ */
+ uint32_t scanSpacing;
+};
+
+/**
+ * An entry in regional configuration for DAB.
+ *
+ * Defines a frequency table row for ensembles.
+ */
+struct DabTableEntry {
+ /**
+ * Channel name, i.e. 5A, 7B.
+ *
+ * It must match the following regular expression: /^[A-Z0-9]{2,5}$/.
+ */
+ string label;
+
+ /** Frequency, in kHz. */
+ uint32_t frequency;
+};
+
+/**
* Properties of a given broadcast radio module.
*/
struct Properties {
@@ -363,7 +466,12 @@
* Consists of (from the LSB):
* - 32bit: Station ID number;
* - 4bit: HD Radio subchannel;
- * - 18bit: AMFM_FREQUENCY. // TODO(b/69958777): is it necessary?
+ * - 18bit: AMFM_FREQUENCY.
+ *
+ * While station ID number should be unique globally, it sometimes get
+ * abused by broadcasters (i.e. not being set at all). To ensure local
+ * uniqueness, AMFM_FREQUENCY was added here. Global uniqueness is
+ * a best-effort - see HD_STATION_NAME.
*
* HD Radio subchannel is a value in range 0-7.
* This index is 0-based (where 0 is MPS and 1..7 are SPS),
@@ -375,6 +483,22 @@
HD_STATION_ID_EXT,
/**
+ * 64bit additional identifier for HD Radio.
+ *
+ * Due to Station ID abuse, some HD_STATION_ID_EXT identifiers may be not
+ * globally unique. To provide a best-effort solution, a short version of
+ * station name may be carried as additional identifier and may be used
+ * by the tuner hardware to double-check tuning.
+ *
+ * The name is limited to the first 8 A-Z0-9 characters (lowercase letters
+ * must be converted to uppercase). Encoded in little-endian ASCII:
+ * the first character of the name is the LSB.
+ *
+ * For example: "Abc" is encoded as 0x434241.
+ */
+ HD_STATION_NAME,
+
+ /**
* 28bit compound primary identifier for Digital Audio Broadcasting.
*
* Consists of (from the LSB):
@@ -389,7 +513,7 @@
* The remaining bits should be set to zeros when writing on the chip side
* and ignored when read.
*/
- DAB_SID_EXT = HD_STATION_ID_EXT + 2,
+ DAB_SID_EXT,
/** 16bit */
DAB_ENSEMBLE,
@@ -674,3 +798,55 @@
*/
bool excludeModifications;
};
+
+/**
+ * Type of an announcement.
+ *
+ * It maps to different announcement types per each radio technology.
+ */
+enum AnnouncementType : uint8_t {
+ /** DAB alarm, RDS emergency program type (PTY 31). */
+ EMERGENCY = 1,
+
+ /** DAB warning. */
+ WARNING,
+
+ /** DAB road traffic, RDS TA, HD Radio transportation. */
+ TRAFFIC,
+
+ /** Weather. */
+ WEATHER,
+
+ /** News. */
+ NEWS,
+
+ /** DAB event, special event. */
+ EVENT,
+
+ /** DAB sport report, RDS sports. */
+ SPORT,
+
+ /** All others. */
+ MISC,
+};
+
+/**
+ * A pointer to a station broadcasting active announcement.
+ */
+struct Announcement {
+ /**
+ * Program selector to tune to the announcement.
+ */
+ ProgramSelector selector;
+
+ /** Announcement type. */
+ AnnouncementType type;
+
+ /**
+ * Vendor-specific information.
+ *
+ * It may be used for extra features, not supported by the platform,
+ * for example: com.me.hdradio.urgency=100; com.me.hdradio.certainity=50.
+ */
+ vec<VendorKeyValue> vendorInfo;
+};
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index 6017b15..6940bca 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -17,6 +17,9 @@
cc_test {
name: "VtsHalBroadcastradioV2_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
+ cppflags: [
+ "-std=c++1z",
+ ],
srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
static_libs: [
"android.hardware.broadcastradio@2.0",
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index cbe6288..1111478 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -26,9 +26,12 @@
#include <broadcastradio-vts-utils/call-barrier.h>
#include <broadcastradio-vts-utils/mock-timeout.h>
#include <broadcastradio-vts-utils/pointer-utils.h>
+#include <cutils/bitops.h>
#include <gmock/gmock.h>
#include <chrono>
+#include <optional>
+#include <regex>
namespace android {
namespace hardware {
@@ -87,12 +90,18 @@
utils::ProgramInfoSet mProgramList;
};
+struct AnnouncementObserverMock : public IAnnouncementObserver {
+ MOCK_METHOD1(onListUpdated, Return<void>(const hidl_vec<Announcement>&));
+};
+
class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase {
protected:
virtual void SetUp() override;
virtual void TearDown() override;
bool openSession();
+ bool getAmFmRegionConfig(bool full, AmFmRegionConfig* config);
+ std::optional<utils::ProgramInfoSet> getProgramList();
sp<IBroadcastRadio> mModule;
Properties mProperties;
@@ -159,6 +168,41 @@
return nullptr != mSession.get();
}
+bool BroadcastRadioHalTest::getAmFmRegionConfig(bool full, AmFmRegionConfig* config) {
+ auto halResult = Result::UNKNOWN_ERROR;
+ auto cb = [&](Result result, AmFmRegionConfig configCb) {
+ halResult = result;
+ if (config) *config = configCb;
+ };
+
+ auto hidlResult = mModule->getAmFmRegionConfig(full, cb);
+ EXPECT_TRUE(hidlResult.isOk());
+
+ if (halResult == Result::NOT_SUPPORTED) return false;
+
+ EXPECT_EQ(Result::OK, halResult);
+ return halResult == Result::OK;
+}
+
+std::optional<utils::ProgramInfoSet> BroadcastRadioHalTest::getProgramList() {
+ EXPECT_TIMEOUT_CALL(*mCallback, onProgramListReady).Times(AnyNumber());
+
+ auto startResult = mSession->startProgramListUpdates({});
+ if (startResult == Result::NOT_SUPPORTED) {
+ printSkipped("Program list not supported");
+ return nullopt;
+ }
+ EXPECT_EQ(Result::OK, startResult);
+ if (startResult != Result::OK) return nullopt;
+
+ EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onProgramListReady, timeout::programListScan);
+
+ auto stopResult = mSession->stopProgramListUpdates();
+ EXPECT_TRUE(stopResult.isOk());
+
+ return mCallback->mProgramList;
+}
+
/**
* Test session opening.
*
@@ -181,6 +225,127 @@
ASSERT_TRUE(openSession());
}
+static bool isValidAmFmFreq(uint64_t freq) {
+ auto id = utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq);
+ return utils::isValid(id);
+}
+
+static void validateRange(const AmFmBandRange& range) {
+ EXPECT_TRUE(isValidAmFmFreq(range.lowerBound));
+ EXPECT_TRUE(isValidAmFmFreq(range.upperBound));
+ EXPECT_LT(range.lowerBound, range.upperBound);
+ EXPECT_GT(range.spacing, 0u);
+ EXPECT_EQ(0u, (range.upperBound - range.lowerBound) % range.spacing);
+}
+
+static bool supportsFM(const AmFmRegionConfig& config) {
+ for (auto&& range : config.ranges) {
+ if (utils::getBand(range.lowerBound) == utils::FrequencyBand::FM) return true;
+ }
+ return false;
+}
+
+/**
+ * Test fetching AM/FM regional configuration.
+ *
+ * Verifies that:
+ * - AM/FM regional configuration is either set at startup or not supported at all by the hardware;
+ * - there is at least one AM/FM band configured;
+ * - FM Deemphasis and RDS are correctly configured for FM-capable radio;
+ * - all channel grids (frequency ranges and spacings) are valid;
+ * - scan spacing is a multiply of manual spacing value.
+ */
+TEST_F(BroadcastRadioHalTest, GetAmFmRegionConfig) {
+ AmFmRegionConfig config;
+ bool supported = getAmFmRegionConfig(false, &config);
+ if (!supported) {
+ printSkipped("AM/FM not supported");
+ return;
+ }
+
+ EXPECT_GT(config.ranges.size(), 0u);
+ EXPECT_LE(popcountll(config.fmDeemphasis), 1);
+ EXPECT_LE(popcountll(config.fmRds), 1);
+
+ for (auto&& range : config.ranges) {
+ validateRange(range);
+ EXPECT_EQ(0u, range.scanSpacing % range.spacing);
+ EXPECT_GE(range.scanSpacing, range.spacing);
+ }
+
+ if (supportsFM(config)) {
+ EXPECT_EQ(popcountll(config.fmDeemphasis), 1);
+ }
+}
+
+/**
+ * Test fetching AM/FM regional capabilities.
+ *
+ * Verifies that:
+ * - AM/FM regional capabilities are either available or not supported at all by the hardware;
+ * - there is at least one AM/FM range supported;
+ * - there is at least one de-emphasis filter mode supported for FM-capable radio;
+ * - all channel grids (frequency ranges and spacings) are valid;
+ * - scan spacing is not set.
+ */
+TEST_F(BroadcastRadioHalTest, GetAmFmRegionConfigCapabilities) {
+ AmFmRegionConfig config;
+ bool supported = getAmFmRegionConfig(true, &config);
+ if (!supported) {
+ printSkipped("AM/FM not supported");
+ return;
+ }
+
+ EXPECT_GT(config.ranges.size(), 0u);
+
+ for (auto&& range : config.ranges) {
+ validateRange(range);
+ EXPECT_EQ(0u, range.scanSpacing);
+ }
+
+ if (supportsFM(config)) {
+ EXPECT_GE(popcountll(config.fmDeemphasis), 1);
+ }
+}
+
+/**
+ * Test fetching DAB regional configuration.
+ *
+ * Verifies that:
+ * - DAB regional configuration is either set at startup or not supported at all by the hardware;
+ * - all channel labels match correct format;
+ * - all channel frequencies are in correct range.
+ */
+TEST_F(BroadcastRadioHalTest, GetDabRegionConfig) {
+ Result halResult;
+ hidl_vec<DabTableEntry> config;
+ auto cb = [&](Result result, hidl_vec<DabTableEntry> configCb) {
+ halResult = result;
+ config = configCb;
+ };
+ auto hidlResult = mModule->getDabRegionConfig(cb);
+ ASSERT_TRUE(hidlResult.isOk());
+
+ if (halResult == Result::NOT_SUPPORTED) {
+ printSkipped("DAB not supported");
+ return;
+ }
+ ASSERT_EQ(Result::OK, halResult);
+
+ std::regex re("^[A-Z0-9]{2,5}$");
+ // double-check correctness of the test
+ ASSERT_TRUE(std::regex_match("5A", re));
+ ASSERT_FALSE(std::regex_match("5a", re));
+ ASSERT_FALSE(std::regex_match("123ABC", re));
+
+ for (auto&& entry : config) {
+ EXPECT_TRUE(std::regex_match(std::string(entry.label), re));
+
+ auto id = utils::make_identifier(IdentifierType::DAB_FREQUENCY, entry.frequency);
+ EXPECT_TRUE(utils::isValid(id));
+ }
+}
+
/**
* Test tuning with FM selector.
*
@@ -505,19 +670,69 @@
TEST_F(BroadcastRadioHalTest, GetProgramList) {
ASSERT_TRUE(openSession());
- EXPECT_TIMEOUT_CALL(*mCallback, onProgramListReady).Times(AnyNumber());
+ getProgramList();
+}
- auto startResult = mSession->startProgramListUpdates({});
- if (startResult == Result::NOT_SUPPORTED) {
- printSkipped("Program list not supported");
+/**
+ * Test HD_STATION_NAME correctness.
+ *
+ * Verifies that if a program on the list contains HD_STATION_NAME identifier:
+ * - the program provides station name in its metadata;
+ * - the identifier matches the name;
+ * - there is only one identifier of that type.
+ */
+TEST_F(BroadcastRadioHalTest, HdRadioStationNameId) {
+ ASSERT_TRUE(openSession());
+
+ auto list = getProgramList();
+ if (!list) return;
+
+ for (auto&& program : *list) {
+ auto nameIds = utils::getAllIds(program.selector, IdentifierType::HD_STATION_NAME);
+ EXPECT_LE(nameIds.size(), 1u);
+ if (nameIds.size() == 0) continue;
+
+ auto name = utils::getMetadataString(program, MetadataKey::PROGRAM_NAME);
+ if (!name) name = utils::getMetadataString(program, MetadataKey::RDS_PS);
+ ASSERT_TRUE(name.has_value());
+
+ auto expectedId = utils::make_hdradio_station_name(*name);
+ EXPECT_EQ(expectedId.value, nameIds[0]);
+ }
+}
+
+/**
+ * Test announcement observer registration.
+ *
+ * Verifies that:
+ * - registerAnnouncementObserver either succeeds or returns NOT_SUPPORTED;
+ * - if it succeeds, it returns a valid close handle (which is a nullptr otherwise);
+ * - closing handle does not crash.
+ */
+TEST_F(BroadcastRadioHalTest, AnnouncementObserverRegistration) {
+ sp<AnnouncementObserverMock> observer = new AnnouncementObserverMock();
+
+ Result halResult = Result::UNKNOWN_ERROR;
+ sp<ICloseHandle> closeHandle = nullptr;
+ auto cb = [&](Result result, const sp<ICloseHandle>& closeHandle_) {
+ halResult = result;
+ closeHandle = closeHandle_;
+ };
+
+ auto hidlResult =
+ mModule->registerAnnouncementObserver({AnnouncementType::EMERGENCY}, observer, cb);
+ ASSERT_TRUE(hidlResult.isOk());
+
+ if (halResult == Result::NOT_SUPPORTED) {
+ ASSERT_EQ(nullptr, closeHandle.get());
+ printSkipped("Announcements not supported");
return;
}
- ASSERT_EQ(Result::OK, startResult);
- EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onProgramListReady, timeout::programListScan);
+ ASSERT_EQ(Result::OK, halResult);
+ ASSERT_NE(nullptr, closeHandle.get());
- auto stopResult = mSession->stopProgramListUpdates();
- EXPECT_TRUE(stopResult.isOk());
+ closeHandle->close();
}
// TODO(b/70939328): test ProgramInfo's currentlyTunedId and
diff --git a/broadcastradio/common/tests/Android.bp b/broadcastradio/common/tests/Android.bp
index 512c02e..f6a3b6f 100644
--- a/broadcastradio/common/tests/Android.bp
+++ b/broadcastradio/common/tests/Android.bp
@@ -22,6 +22,9 @@
"-Wextra",
"-Werror",
],
+ cppflags: [
+ "-std=c++1z",
+ ],
srcs: [
"CommonXX_test.cpp",
],
@@ -43,8 +46,12 @@
"-Wextra",
"-Werror",
],
+ cppflags: [
+ "-std=c++1z",
+ ],
srcs: [
"IdentifierIterator_test.cpp",
+ "ProgramIdentifier_test.cpp",
],
static_libs: [
"android.hardware.broadcastradio@common-utils-2x-lib",
diff --git a/broadcastradio/common/tests/ProgramIdentifier_test.cpp b/broadcastradio/common/tests/ProgramIdentifier_test.cpp
new file mode 100644
index 0000000..51ad014
--- /dev/null
+++ b/broadcastradio/common/tests/ProgramIdentifier_test.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <broadcastradio-utils-2x/Utils.h>
+#include <gtest/gtest.h>
+
+#include <optional>
+
+namespace {
+
+namespace utils = android::hardware::broadcastradio::utils;
+
+TEST(ProgramIdentifierTest, hdRadioStationName) {
+ auto verify = [](std::string name, uint64_t nameId) {
+ auto id = utils::make_hdradio_station_name(name);
+ EXPECT_EQ(nameId, id.value) << "Failed to convert '" << name << "'";
+ };
+
+ verify("", 0);
+ verify("Abc", 0x434241);
+ verify("Some Station 1", 0x54415453454d4f53);
+ verify("Station1", 0x314e4f4954415453);
+ verify("!@#$%^&*()_+", 0);
+ verify("-=[]{};':\"0", 0x30);
+}
+
+} // anonymous namespace
diff --git a/broadcastradio/common/utils2x/Android.bp b/broadcastradio/common/utils2x/Android.bp
index c6b94af..aab94f2 100644
--- a/broadcastradio/common/utils2x/Android.bp
+++ b/broadcastradio/common/utils2x/Android.bp
@@ -23,6 +23,9 @@
"-Wextra",
"-Werror",
],
+ cppflags: [
+ "-std=c++1z",
+ ],
srcs: [
"Utils.cpp",
],
diff --git a/broadcastradio/common/utils2x/Utils.cpp b/broadcastradio/common/utils2x/Utils.cpp
index e0337b4..6fe9554 100644
--- a/broadcastradio/common/utils2x/Utils.cpp
+++ b/broadcastradio/common/utils2x/Utils.cpp
@@ -89,6 +89,18 @@
return IdentifierIterator(sel) + 1 /* primary id */ + sel.secondaryIds.size();
}
+FrequencyBand getBand(uint64_t freq) {
+ // keep in sync with
+ // frameworks/base/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
+ if (freq < 30) return FrequencyBand::UNKNOWN;
+ if (freq < 500) return FrequencyBand::AM_LW;
+ if (freq < 1705) return FrequencyBand::AM_MW;
+ if (freq < 30000) return FrequencyBand::AM_SW;
+ if (freq < 60000) return FrequencyBand::UNKNOWN;
+ if (freq < 110000) return FrequencyBand::FM;
+ return FrequencyBand::UNKNOWN;
+}
+
static bool bothHaveId(const ProgramSelector& a, const ProgramSelector& b,
const IdentifierType type) {
return hasId(a, type) && hasId(b, type);
@@ -194,7 +206,7 @@
return false;
}
-static bool isValid(const ProgramIdentifier& id) {
+bool isValid(const ProgramIdentifier& id) {
auto val = id.value;
bool valid = true;
@@ -209,8 +221,10 @@
case IdentifierType::INVALID:
expect(false, "IdentifierType::INVALID");
break;
- case IdentifierType::AMFM_FREQUENCY:
case IdentifierType::DAB_FREQUENCY:
+ expect(val > 100000u, "f > 100MHz");
+ // fallthrough
+ case IdentifierType::AMFM_FREQUENCY:
case IdentifierType::DRMO_FREQUENCY:
expect(val > 100u, "f > 100kHz");
expect(val < 10000000u, "f < 10GHz");
@@ -231,6 +245,15 @@
expect(freq < 10000000u, "f < 10GHz");
break;
}
+ case IdentifierType::HD_STATION_NAME: {
+ while (val > 0) {
+ auto ch = static_cast<char>(val & 0xFF);
+ val >>= 8;
+ expect((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'),
+ "HD_STATION_NAME does not match [A-Z0-9]+");
+ }
+ break;
+ }
case IdentifierType::DAB_SID_EXT: {
auto sid = val & 0xFFFF; // 16bit
val >>= 16;
@@ -353,6 +376,40 @@
}
}
+std::optional<std::string> getMetadataString(const V2_0::ProgramInfo& info,
+ const V2_0::MetadataKey key) {
+ auto isKey = [key](const V2_0::Metadata& item) {
+ return static_cast<V2_0::MetadataKey>(item.key) == key;
+ };
+
+ auto it = std::find_if(info.metadata.begin(), info.metadata.end(), isKey);
+ if (it == info.metadata.end()) return std::nullopt;
+
+ return it->stringValue;
+}
+
+V2_0::ProgramIdentifier make_hdradio_station_name(const std::string& name) {
+ constexpr size_t maxlen = 8;
+
+ std::string shortName;
+ shortName.reserve(maxlen);
+
+ auto&& loc = std::locale::classic();
+ for (char ch : name) {
+ if (!std::isalnum(ch, loc)) continue;
+ shortName.push_back(std::toupper(ch, loc));
+ if (shortName.length() >= maxlen) break;
+ }
+
+ uint64_t val = 0;
+ for (auto rit = shortName.rbegin(); rit != shortName.rend(); ++rit) {
+ val <<= 8;
+ val |= static_cast<uint8_t>(*rit);
+ }
+
+ return make_identifier(IdentifierType::HD_STATION_NAME, val);
+}
+
} // namespace utils
} // namespace broadcastradio
} // namespace hardware
diff --git a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
index bac11fd..5e51941 100644
--- a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
+++ b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
@@ -18,6 +18,7 @@
#include <android/hardware/broadcastradio/2.0/types.h>
#include <chrono>
+#include <optional>
#include <queue>
#include <thread>
#include <unordered_set>
@@ -27,6 +28,14 @@
namespace broadcastradio {
namespace utils {
+enum class FrequencyBand {
+ UNKNOWN,
+ FM,
+ AM_LW,
+ AM_MW,
+ AM_SW,
+};
+
V2_0::IdentifierType getType(uint32_t typeAsInt);
V2_0::IdentifierType getType(const V2_0::ProgramIdentifier& id);
@@ -64,6 +73,16 @@
IdentifierIterator end(const V2_0::ProgramSelector& sel);
/**
+ * Guesses band from the frequency value.
+ *
+ * The band bounds are not exact to cover multiple regions.
+ * The function is biased towards success, i.e. it never returns
+ * FrequencyBand::UNKNOWN for correct frequency, but a result for
+ * incorrect one is undefined (it doesn't have to return UNKNOWN).
+ */
+FrequencyBand getBand(uint64_t frequency);
+
+/**
* Checks, if {@code pointer} tunes to {@channel}.
*
* For example, having a channel {AMFM_FREQUENCY = 103.3}:
@@ -105,6 +124,7 @@
*/
bool isSupported(const V2_0::Properties& prop, const V2_0::ProgramSelector& sel);
+bool isValid(const V2_0::ProgramIdentifier& id);
bool isValid(const V2_0::ProgramSelector& sel);
V2_0::ProgramIdentifier make_identifier(V2_0::IdentifierType type, uint64_t value);
@@ -127,6 +147,11 @@
void updateProgramList(ProgramInfoSet& list, const V2_0::ProgramListChunk& chunk);
+std::optional<std::string> getMetadataString(const V2_0::ProgramInfo& info,
+ const V2_0::MetadataKey key);
+
+V2_0::ProgramIdentifier make_hdradio_station_name(const std::string& name);
+
} // namespace utils
} // namespace broadcastradio
} // namespace hardware
diff --git a/gnss/1.0/default/Gnss.cpp b/gnss/1.0/default/Gnss.cpp
index f362749..32c131c 100644
--- a/gnss/1.0/default/Gnss.cpp
+++ b/gnss/1.0/default/Gnss.cpp
@@ -121,7 +121,7 @@
svStatus.numSvs = status->num_svs;
if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
- ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
+ ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
}
@@ -191,7 +191,7 @@
* GnssMax::SVS_COUNT entries.
*/
if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
- ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
+ ALOGW("Too many satellites %u. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
}
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index cdb9bf6..3e678bb 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -19,6 +19,7 @@
"android.hidl.base@1.0",
],
types: [
+ "CardStatus",
"CellIdentityCdma",
"CellIdentityGsm",
"CellIdentityLte",
@@ -35,6 +36,8 @@
"NetworkScanResult",
"RadioConst",
"ScanIntervalRange",
+ "SimSlotStatus",
+ "SlotState",
],
gen_java: true,
}
diff --git a/radio/1.2/IRadio.hal b/radio/1.2/IRadio.hal
index 6ae78a0..73f1024 100644
--- a/radio/1.2/IRadio.hal
+++ b/radio/1.2/IRadio.hal
@@ -37,4 +37,46 @@
* Response function is IRadioResponse.startNetworkScanResponse()
*/
oneway startNetworkScan_1_2(int32_t serial, NetworkScanRequest request);
+
+ /**
+ * Get SIM Slot status.
+ *
+ * Request provides the slot status of all active and inactive SIM slots and whether card is
+ * present in the slots or not.
+ *
+ * @param serial Serial number of request.
+ *
+ * Response callback is IRadioResponse.getSimSlotsStatusResponse()
+ */
+ oneway getSimSlotsStatus(int32_t serial);
+
+ /**
+ * Set SIM Slot mapping.
+
+ * Maps the logical slots to the physical slots. Logical slot is the slot that is seen by modem.
+ * Physical slot is the actual physical slot. Request maps the physical slot to logical slot.
+ * Logical slots that are already mapped to the requested physical slot are not impacted.
+ *
+ * Example no. of logical slots 1 and physical slots 2:
+ * The only logical slot (index 0) can be mapped to first physical slot (value 0) or second
+ * physical slot(value 1), while the other physical slot remains unmapped and inactive.
+ * slotMap[0] = 1 or slotMap[0] = 0
+ *
+ * Example no. of logical slots 2 and physical slots 2:
+ * First logical slot (index 0) can be mapped to physical slot 1 or 2 and other logical slot
+ * can be mapped to other physical slot. Each logical slot must be mapped to a physical slot.
+ * slotMap[0] = 0 and slotMap[1] = 1 or slotMap[0] = 1 and slotMap[1] = 0
+ *
+ * @param serial Serial number of request
+ * @param slotMap Logical to physical slot mapping, size == no. of radio instances. Index is
+ * mapping to logical slot and value to physical slot, need to provide all the slots
+ * mapping when sending request in case of multi slot device.
+ * EX: uint32_t slotMap[logical slot] = physical slot
+ * index 0 is the first logical_slot number of logical slots is equal to number of Radio
+ * instances and number of physical slots is equal to size of slotStatus in
+ * getSimSlotsStatusResponse
+ *
+ * Response callback is IRadioResponse.setSimSlotsMappingResponse()
+ */
+ oneway setSimSlotsMapping(int32_t serial, vec<uint32_t> slotMap);
};
diff --git a/radio/1.2/IRadioIndication.hal b/radio/1.2/IRadioIndication.hal
index 5d3efcf..4aae74d 100644
--- a/radio/1.2/IRadioIndication.hal
+++ b/radio/1.2/IRadioIndication.hal
@@ -28,4 +28,13 @@
* Incremental network scan results
*/
oneway networkScanResult_1_2(RadioIndicationType type, NetworkScanResult result);
-};
\ No newline at end of file
+
+ /**
+ * Indicates SIM slot status change.
+ *
+ * @param type Type of radio indication
+ * @param slotStatus new slot status info with size equals to the number of physical slots on
+ * the device
+ */
+ oneway simSlotsStatusChanged(RadioIndicationType type, vec<SimSlotStatus> slotStatus);
+};
diff --git a/radio/1.2/IRadioResponse.hal b/radio/1.2/IRadioResponse.hal
index 5bfbbae..cf6bc00 100644
--- a/radio/1.2/IRadioResponse.hal
+++ b/radio/1.2/IRadioResponse.hal
@@ -41,4 +41,42 @@
* RadioError:CANCELLED
*/
oneway getCellInfoListResponse_1_2(RadioResponseInfo info, vec<CellInfo> cellInfo);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param cardStatus ICC card status as defined by CardStatus in types.hal
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ */
+ oneway getIccCardStatusResponse_1_2(RadioResponseInfo info, CardStatus cardStatus);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param slotStatus Sim slot struct containing all the physical SIM slots info with size
+ * equals to the number of physical slots on the device
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:NO_MEMORY
+ * RadioError:INTERNAL_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INVALID_ARGUMENTS
+ */
+ oneway getSimSlotsStatusResponse(RadioResponseInfo info, vec<SimSlotStatus> slotStatus);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:NO_MEMORY
+ * RadioError:INTERNAL_ERR
+ * RadioError:MODEM_ERR
+ */
+ oneway setSimSlotsMappingResponse(RadioResponseInfo info);
};
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index 52af575..1e28d3b 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -17,6 +17,8 @@
package android.hardware.radio@1.2;
import @1.0::CdmaSignalStrength;
+import @1.0::CardState;
+import @1.0::CardStatus;
import @1.0::CellIdentityCdma;
import @1.0::CellIdentityGsm;
import @1.0::CellIdentityLte;
@@ -187,37 +189,97 @@
* Cell type for selecting from union CellInfo.
*/
CellInfoType cellInfoType;
- /*
+ /**
* True if this cell is registered false if not registered.
*/
bool registered;
- /*
+ /**
* Type of time stamp represented by timeStamp.
*/
TimeStampType timeStampType;
- /*
+ /**
* Time in nanos as returned by ril_nano_time.
*/
uint64_t timeStamp;
- /*
+ /**
* Only one of the below vectors must be of size 1 based on the CellInfoType and others must be
* of size 0.
*/
vec<CellInfoGsm> gsm;
- /*
+ /**
* Valid only if type = cdma and size = 1 else must be empty.
*/
vec<CellInfoCdma> cdma;
- /*
+ /**
* Valid only if type = lte and size = 1 else must be empty.
*/
vec<CellInfoLte> lte;
- /*
+ /**
* Valid only if type = wcdma and size = 1 else must be empty.
*/
vec<CellInfoWcdma> wcdma;
- /*
+ /**
* Valid only if type = tdscdma and size = 1 else must be empty.
*/
vec<CellInfoTdscdma> tdscdma;
};
+
+enum SlotState : int32_t {
+ /**
+ * Physical slot is inactive
+ */
+ INACTIVE = 0x00,
+ /**
+ * Physical slot is active
+ */
+ ACTIVE = 0x01,
+};
+
+struct CardStatus {
+ @1.0::CardStatus base;
+ uint32_t physicalSlotId;
+ /**
+ * An Answer To Reset (ATR) is a message output by a Smart Card conforming to ISO/IEC 7816
+ * standards, following electrical reset of the card's chip. The ATR conveys information about
+ * the communication parameters proposed by the card, and the card's nature and state.
+ *
+ * This data is applicable only when cardState is CardState:PRESENT.
+ */
+ string atr;
+ /**
+ * Integrated Circuit Card IDentifier (ICCID) is Unique Identifier of the SIM CARD. File is
+ * located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
+ * the ITU-T recommendation E.118 ISO/IEC 7816.
+ *
+ * This data is applicable only when cardState is CardState:PRESENT.
+ */
+ string iccid;
+};
+
+struct SimSlotStatus {
+ /**
+ * Card state in the physical slot
+ */
+ CardState cardState;
+ /**
+ * Slot state Active/Inactive
+ */
+ SlotState slotState;
+ /**
+ * An Answer To Reset (ATR) is a message output by a Smart Card conforming to ISO/IEC 7816
+ * standards, following electrical reset of the card's chip. The ATR conveys information about
+ * the communication parameters proposed by the card, and the card's nature and state.
+ *
+ * This data is applicable only when cardState is CardState:PRESENT.
+ */
+ string atr;
+ uint32_t logicalSlotId;
+ /**
+ * Integrated Circuit Card IDentifier (ICCID) is Unique Identifier of the SIM CARD. File is
+ * located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
+ * the ITU-T recommendation E.118 ISO/IEC 7816.
+ *
+ * This data is applicable only when cardState is CardState:PRESENT.
+ */
+ string iccid;
+};
diff --git a/tests/memory/1.0/IMemoryTest.hal b/tests/memory/1.0/IMemoryTest.hal
index b20859c..3c4d4f3 100644
--- a/tests/memory/1.0/IMemoryTest.hal
+++ b/tests/memory/1.0/IMemoryTest.hal
@@ -23,6 +23,6 @@
haveSomeMemory(memory mem) generates(memory mem);
fillMemory(memory memory_in, uint8_t filler);
haveSomeMemoryBlock(MemoryBlock blk) generates(MemoryBlock blk);
- set(memory mem) generates();
+ set(memory mem);
get()generates(IMemoryToken token);
};