merge b2g-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-10-01 15:05:31 +02:00
commit 266376bb09
53 changed files with 1903 additions and 495 deletions

View File

@ -19,7 +19,11 @@
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml"
"{workdir}/sources.xml",
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>

View File

@ -22,7 +22,11 @@
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml"
"{workdir}/sources.xml",
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -22,7 +22,11 @@
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml"
"{workdir}/sources.xml",
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "7f097f40e32ecba580890ce1d3df2a493641bdec",
"revision": "aa3ab2d389dce3ba351a897b4ae56f1fe9e1780d",
"repo_path": "/integration/gaia-central"
}

View File

@ -16,6 +16,12 @@
"{workdir}/sources.xml",
"{workdir}/out/target/product/hamachi/*.mar"
],
"zip_files": [
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1",

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -21,7 +21,11 @@
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml"
"{workdir}/sources.xml",
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -22,7 +22,11 @@
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml"
"{workdir}/sources.xml",
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>

View File

@ -16,7 +16,11 @@
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml"
"{workdir}/sources.xml",
"{workdir}/profile.sh",
["{workdir}/gecko/tools/profiler/merge-profiles.py", "gecko/tools/profiler/"],
["{workdir}/scripts/profile-symbolicate.py", "scripts/"],
["{workdir}/gecko/tools/rb/fix_stack_using_bpsyms.py", "gecko/tools/rb/"]
],
"env": {
"VARIANT": "user",

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a23d2c490b39c4699c9375e25c4acdf396a2fa85"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -796,6 +796,7 @@ GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll")
GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged")
GK_ATOM(onmoznetworkupload, "onmoznetworkupload")
GK_ATOM(onmoznetworkdownload, "onmoznetworkdownload")
GK_ATOM(onnewrdsgroup, "onnewrdsgroup")
GK_ATOM(onnoupdate, "onnoupdate")
GK_ATOM(onobsolete, "onobsolete")
GK_ATOM(ononline, "ononline")
@ -812,11 +813,16 @@ GK_ATOM(onpairingconfirmationreq, "onpairingconfirmationreq")
GK_ATOM(onpairingconsentreq, "onpairingconsentreq")
GK_ATOM(onpaste, "onpaste")
GK_ATOM(onpendingchange, "onpendingchange")
GK_ATOM(onpichange, "onpichange")
GK_ATOM(onpopuphidden, "onpopuphidden")
GK_ATOM(onpopuphiding, "onpopuphiding")
GK_ATOM(onpopupshowing, "onpopupshowing")
GK_ATOM(onpopupshown, "onpopupshown")
GK_ATOM(onpschange, "onpschange")
GK_ATOM(onptychange, "onptychange")
GK_ATOM(onradiostatechange, "onradiostatechange")
GK_ATOM(onrdsdisabled, "onrdsdisabled")
GK_ATOM(onrdsenabled, "onrdsenabled")
GK_ATOM(onreaderror, "onreaderror")
GK_ATOM(onreadsuccess, "onreadsuccess")
GK_ATOM(onready, "onready")
@ -831,6 +837,7 @@ GK_ATOM(onrequestmediaplaystatus, "onrequestmediaplaystatus")
GK_ATOM(onreset, "onreset")
GK_ATOM(onresuming, "onresuming")
GK_ATOM(onresize, "onresize")
GK_ATOM(onrtchange, "onrtchange")
GK_ATOM(onscostatuschanged, "onscostatuschanged")
GK_ATOM(onscroll, "onscroll")
GK_ATOM(onselect, "onselect")

View File

@ -10,6 +10,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "BluetoothChild.h"
#include "MainThreadUtils.h"

View File

@ -13,6 +13,7 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PFMRadioChild.h"
#include "mozilla/dom/FMRadioService.h"
#include "mozilla/dom/TypedArray.h"
#include "DOMRequest.h"
#include "nsDOMClassInfo.h"
#include "nsIDocShell.h"
@ -105,6 +106,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(FMRadioRequest, DOMRequest)
FMRadio::FMRadio()
: mHeadphoneState(SWITCH_STATE_OFF)
, mRdsGroupMask(0)
, mAudioChannelAgentEnabled(false)
, mHasInternalAntenna(false)
, mIsShutdown(false)
@ -220,6 +222,28 @@ FMRadio::Notify(const FMRadioEventType& aType)
DispatchTrustedEvent(NS_LITERAL_STRING("disabled"));
}
break;
case RDSEnabledChanged:
if (RdsEnabled()) {
DispatchTrustedEvent(NS_LITERAL_STRING("rdsenabled"));
} else {
DispatchTrustedEvent(NS_LITERAL_STRING("rdsdisabled"));
}
break;
case PIChanged:
DispatchTrustedEvent(NS_LITERAL_STRING("pichange"));
break;
case PSChanged:
DispatchTrustedEvent(NS_LITERAL_STRING("pschange"));
break;
case RadiotextChanged:
DispatchTrustedEvent(NS_LITERAL_STRING("rtchange"));
break;
case PTYChanged:
DispatchTrustedEvent(NS_LITERAL_STRING("ptychange"));
break;
case NewRDSGroup:
DispatchTrustedEvent(NS_LITERAL_STRING("newrdsgroup"));
break;
default:
MOZ_CRASH();
}
@ -232,6 +256,12 @@ FMRadio::Enabled()
return IFMRadioService::Singleton()->IsEnabled();
}
bool
FMRadio::RdsEnabled()
{
return IFMRadioService::Singleton()->IsRDSEnabled();
}
bool
FMRadio::AntennaAvailable() const
{
@ -265,6 +295,69 @@ FMRadio::ChannelWidth() const
return IFMRadioService::Singleton()->GetChannelWidth();
}
uint32_t
FMRadio::RdsGroupMask() const
{
return mRdsGroupMask;
}
void
FMRadio::SetRdsGroupMask(uint32_t aRdsGroupMask)
{
mRdsGroupMask = aRdsGroupMask;
IFMRadioService::Singleton()->SetRDSGroupMask(aRdsGroupMask);
}
Nullable<unsigned short>
FMRadio::GetPi() const
{
return IFMRadioService::Singleton()->GetPi();
}
Nullable<uint8_t>
FMRadio::GetPty() const
{
return IFMRadioService::Singleton()->GetPty();
}
void
FMRadio::GetPs(DOMString& aPsname) const
{
if (!IFMRadioService::Singleton()->GetPs(aPsname)) {
aPsname.SetNull();
}
}
void
FMRadio::GetRt(DOMString& aRadiotext) const
{
if (!IFMRadioService::Singleton()->GetRt(aRadiotext)) {
aRadiotext.SetNull();
}
}
void
FMRadio::GetRdsgroup(JSContext* cx, JS::MutableHandle<JSObject*> retval)
{
uint64_t group;
if (!IFMRadioService::Singleton()->GetRdsgroup(group)) {
return;
}
JSObject *rdsgroup = Uint16Array::Create(cx, this, 4);
uint16_t *data = JS_GetUint16ArrayData(rdsgroup);
data[3] = group & 0xFFFF;
group >>= 16;
data[2] = group & 0xFFFF;
group >>= 16;
data[1] = group & 0xFFFF;
group >>= 16;
data[0] = group & 0xFFFF;
JS::ExposeObjectToActiveJS(rdsgroup);
retval.set(rdsgroup);
}
already_AddRefed<DOMRequest>
FMRadio::Enable(double aFrequency)
{
@ -350,6 +443,32 @@ FMRadio::CancelSeek()
return r.forget();
}
already_AddRefed<DOMRequest>
FMRadio::EnableRDS()
{
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
if (!win) {
return nullptr;
}
nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
IFMRadioService::Singleton()->EnableRDS(r);
return r.forget();
}
already_AddRefed<DOMRequest>
FMRadio::DisableRDS()
{
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
if (!win) {
return nullptr;
}
nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
FMRadioService::Singleton()->DisableRDS(r);
return r.forget();
}
NS_IMETHODIMP
FMRadio::HandleEvent(nsIDOMEvent* aEvent)
{

View File

@ -55,6 +55,8 @@ public:
static bool Enabled();
bool RdsEnabled();
bool AntennaAvailable() const;
Nullable<double> GetFrequency() const;
@ -65,6 +67,20 @@ public:
double ChannelWidth() const;
uint32_t RdsGroupMask() const;
void SetRdsGroupMask(uint32_t aRdsGroupMask);
Nullable<unsigned short> GetPi() const;
Nullable<uint8_t> GetPty() const;
void GetPs(DOMString& aPsname) const;
void GetRt(DOMString& aRadiotext) const;
void GetRdsgroup(JSContext* cx, JS::MutableHandle<JSObject*> retval);
already_AddRefed<DOMRequest> Enable(double aFrequency);
already_AddRefed<DOMRequest> Disable();
@ -77,10 +93,21 @@ public:
already_AddRefed<DOMRequest> CancelSeek();
already_AddRefed<DOMRequest> EnableRDS();
already_AddRefed<DOMRequest> DisableRDS();
IMPL_EVENT_HANDLER(enabled);
IMPL_EVENT_HANDLER(disabled);
IMPL_EVENT_HANDLER(rdsenabled);
IMPL_EVENT_HANDLER(rdsdisabled);
IMPL_EVENT_HANDLER(antennaavailablechange);
IMPL_EVENT_HANDLER(frequencychange);
IMPL_EVENT_HANDLER(pichange);
IMPL_EVENT_HANDLER(ptychange);
IMPL_EVENT_HANDLER(pschange);
IMPL_EVENT_HANDLER(rtchange);
IMPL_EVENT_HANDLER(newrdsgroup);
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
@ -92,6 +119,7 @@ private:
void EnableAudioChannelAgent();
hal::SwitchState mHeadphoneState;
uint32_t mRdsGroupMask;
bool mAudioChannelAgentEnabled;
bool mHasInternalAntenna;
bool mIsShutdown;

View File

@ -30,7 +30,13 @@ BEGIN_FMRADIO_NAMESPACE
enum FMRadioEventType
{
FrequencyChanged,
EnabledChanged
EnabledChanged,
RDSEnabledChanged,
PIChanged,
PSChanged,
PTYChanged,
RadiotextChanged,
NewRDSGroup
};
typedef mozilla::Observer<FMRadioEventType> FMRadioEventObserver;

View File

@ -26,6 +26,8 @@
#define MOZSETTINGS_CHANGED_ID "mozsettings-changed"
#define SETTING_KEY_AIRPLANEMODE_ENABLED "airplaneMode.enabled"
#define DOM_PARSED_RDS_GROUPS ((0x2 << 30) | (0x3 << 4) | (0x3 << 0))
using namespace mozilla::hal;
using mozilla::Preferences;
@ -49,9 +51,26 @@ FMRadioService::FMRadioService()
, mState(Disabled)
, mHasReadAirplaneModeSetting(false)
, mAirplaneModeEnabled(false)
, mRDSEnabled(false)
, mPendingRequest(nullptr)
, mObserverList(FMRadioEventObserverList())
, mRDSGroupMask(0)
, mLastPI(0)
, mPI(0)
, mPTY(0)
, mPISet(false)
, mPTYSet(false)
, mRDSLock("FMRadioService::mRDSLock")
, mPSNameState(0)
, mRadiotextAB(false)
, mRDSGroupSet(false)
, mPSNameSet(false)
, mRadiotextSet(false)
{
memset(mPSName, 0, sizeof(mPSName));
memset(mRadiotext, 0, sizeof(mRadiotext));
memset(mTempPSName, 0, sizeof(mTempPSName));
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
// Read power state and frequency from Hal.
mEnabled = IsFMRadioOn();
@ -110,10 +129,12 @@ FMRadioService::FMRadioService()
}
RegisterFMRadioObserver(this);
RegisterFMRadioRDSObserver(this);
}
FMRadioService::~FMRadioService()
{
UnregisterFMRadioRDSObserver(this);
UnregisterFMRadioObserver(this);
}
@ -277,6 +298,21 @@ private:
FMRadioSeekDirection mDirection;
};
class NotifyRunnable MOZ_FINAL : public nsRunnable
{
public:
NotifyRunnable(FMRadioEventType aType) : mType(aType) { }
NS_IMETHOD Run()
{
FMRadioService::Singleton()->NotifyFMRadioEvent(mType);
return NS_OK;
}
private:
FMRadioEventType mType;
};
void
FMRadioService::TransitionState(const FMRadioResponseType& aResponse,
FMRadioState aState)
@ -374,6 +410,13 @@ FMRadioService::IsEnabled() const
return IsFMRadioOn();
}
bool
FMRadioService::IsRDSEnabled() const
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
return mRDSEnabled;
}
double
FMRadioService::GetFrequency() const
{
@ -407,6 +450,54 @@ FMRadioService::GetChannelWidth() const
return mChannelWidthInKHz / 1000.0;
}
Nullable<unsigned short>
FMRadioService::GetPi() const
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
if (!mPISet) {
return Nullable<unsigned short>();
}
return Nullable<unsigned short>(mPI);
}
Nullable<uint8_t>
FMRadioService::GetPty() const
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
if (!mPTYSet) {
return Nullable<uint8_t>();
}
return Nullable<uint8_t>(mPTY);
}
bool
FMRadioService::GetPs(nsString& aPSName)
{
MutexAutoLock lock(mRDSLock);
if (mPSNameSet) {
aPSName = nsString(mPSName);
}
return mPSNameSet;
}
bool
FMRadioService::GetRt(nsString& aRadiotext)
{
MutexAutoLock lock(mRDSLock);
if (mRadiotextSet) {
aRadiotext = nsString(mRadiotext);
}
return mRadiotextSet;
}
bool
FMRadioService::GetRdsgroup(uint64_t& aRDSGroup)
{
MutexAutoLock lock(mRDSLock);
aRDSGroup = mRDSGroup;
return mRDSGroupSet;
}
void
FMRadioService::Enable(double aFrequencyInMHz,
FMRadioReplyRunnable* aReplyRunnable)
@ -679,6 +770,47 @@ FMRadioService::CancelSeek(FMRadioReplyRunnable* aReplyRunnable)
NS_DispatchToMainThread(aReplyRunnable);
}
void
FMRadioService::SetRDSGroupMask(uint32_t aRDSGroupMask)
{
mRDSGroupMask = aRDSGroupMask;
if (IsFMRadioOn()) {
hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS);
}
}
void
FMRadioService::EnableRDS(FMRadioReplyRunnable* aReplyRunnable)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
MOZ_ASSERT(aReplyRunnable);
mRDSEnabled = true;
if (IsFMRadioOn()) {
hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS);
}
aReplyRunnable->SetReply(SuccessResponse());
NS_DispatchToMainThread(aReplyRunnable);
NS_DispatchToMainThread(new NotifyRunnable(RDSEnabledChanged));
}
void
FMRadioService::DisableRDS(FMRadioReplyRunnable* aReplyRunnable)
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
MOZ_ASSERT(aReplyRunnable);
mRDSEnabled = false;
if (IsFMRadioOn()) {
hal::DisableRDS();
}
aReplyRunnable->SetReply(SuccessResponse());
NS_DispatchToMainThread(aReplyRunnable);
NS_DispatchToMainThread(new NotifyRunnable(RDSEnabledChanged));
}
NS_IMETHODIMP
FMRadioService::Observe(nsISupports* aSubject,
const char* aTopic,
@ -760,10 +892,18 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
// The frequency was changed from '0' to some meaningful number, so we
// should send the `FrequencyChanged` event manually.
NotifyFMRadioEvent(FrequencyChanged);
if (mRDSEnabled) {
hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS);
}
break;
case FM_RADIO_OPERATION_DISABLE:
MOZ_ASSERT(mState == Disabling);
mPISet = false;
mPTYSet = false;
memset(mPSName, 0, sizeof(mPSName));
memset(mRadiotext, 0, sizeof(mRadiotext));
TransitionState(SuccessResponse(), Disabled);
UpdatePowerState();
break;
@ -785,6 +925,274 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
}
}
/* This is defined by the RDS standard */
static const uint16_t sRDSToUnicodeMap[256] = {
// The lower half differs from ASCII in 0x1F, 0x24, 0x5E, 0x7E
// Most control characters are replaced with 0x20 (space)
// 0x0-
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
0x0020, 0x0009, 0x000A, 0x000B, 0x0020, 0x00D0, 0x0020, 0x0020,
// 0x1-
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x00AD,
// 0x2-
0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
// 0x3-
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
// 0x4-
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
// 0x5-
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x2015, 0x005F,
// 0x6-
0x2551, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
// 0x7-
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x00AF, 0x007F,
// 0x8-
0x00E1, 0x00E0, 0x00E9, 0x00E8, 0x00ED, 0x00EC, 0x00F3, 0x00F2,
0x00FA, 0x00F9, 0x00D1, 0x00C7, 0x015E, 0x00DF, 0x00A1, 0x0132,
// 0x9-
0x00E2, 0x00E4, 0x00EA, 0x00EB, 0x00EE, 0x00EF, 0x00F4, 0x00F6,
0x00FB, 0x00FC, 0x00F1, 0x00E7, 0x015F, 0x011F, 0x0131, 0x0133,
// 0xA-
0x00AA, 0x03B1, 0x00A9, 0x2030, 0x011E, 0x011B, 0x0148, 0x0151,
0x03C0, 0x20AC, 0x00A3, 0x0024, 0x2190, 0x2191, 0x2192, 0x2193,
// 0xB-
0x00BA, 0x00B9, 0x00B2, 0x00B3, 0x00B1, 0x0130, 0x0144, 0x0171,
0x03BC, 0x00BF, 0x00F7, 0x00B0, 0x00BC, 0x00BD, 0x00BE, 0x00A7,
// 0xC-
0x00C1, 0x00C0, 0x00C9, 0x00C8, 0x00CD, 0x00CC, 0x00D3, 0x00D2,
0x00DA, 0x00D9, 0x0158, 0x010C, 0x0160, 0x017D, 0x00D0, 0x013F,
// 0xD-
0x00C2, 0x00C4, 0x00CA, 0x00CB, 0x00CE, 0x00CF, 0x00D4, 0x00D6,
0x00DB, 0x00DC, 0x0159, 0x010D, 0x0161, 0x017E, 0x0111, 0x0140,
// 0xE-
0x00C3, 0x00C5, 0x00C6, 0x0152, 0x0177, 0x00DD, 0x00D5, 0x00D8,
0x00DE, 0x014A, 0x0154, 0x0106, 0x015A, 0x0179, 0x0166, 0x00F0,
// 0xF-
0x00E3, 0x00E5, 0x00E6, 0x0153, 0x0175, 0x00FD, 0x00F5, 0x00F8,
0x00FE, 0x014B, 0x0155, 0x0107, 0x015B, 0x017A, 0x0167, 0x0020,
};
void
FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
{
uint16_t blocks[4];
blocks[0] = aRDSGroup.blockA();
blocks[1] = aRDSGroup.blockB();
blocks[2] = aRDSGroup.blockC();
blocks[3] = aRDSGroup.blockD();
/* Bit 11 in block B determines whether this is a type B group. */
uint16_t lastPI = blocks[1] & (1 << 11) ? blocks[2] : mLastPI;
/* Update PI if it's not set or if we get two PI with the new value. */
if ((mPI != blocks[0] && lastPI == blocks[0]) || !mPISet) {
mPI = blocks[0];
if (!mPISet) {
mPSNameState = 0;
mRadiotextState = 0;
memset(mTempPSName, 0, sizeof(mTempPSName));
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
}
mPISet = true;
NS_DispatchToMainThread(new NotifyRunnable(PIChanged));
}
mLastPI = blocks[0];
/* PTY is also updated using the same logic as PI */
uint16_t pty = (blocks[1] >> 5) & 0x1F;
if ((mPTY != pty && pty == mLastPTY) || !mPTYSet) {
mPTY = pty;
mPTYSet = true;
NS_DispatchToMainThread(new NotifyRunnable(PTYChanged));
}
mLastPTY = pty;
uint16_t grouptype = blocks[1] >> 11;
switch (grouptype) {
case 0: // 0a
case 1: // 0b
{
uint16_t segmentAddr = (blocks[1] & 0x3);
// mPSNameState is a bitmask that lets us ensure all segments
// are received before updating the PS name.
if (!segmentAddr) {
mPSNameState = 1;
} else {
mPSNameState |= 1 << segmentAddr;
}
uint16_t offset = segmentAddr << 1;
mTempPSName[offset] = sRDSToUnicodeMap[blocks[3] >> 8];
mTempPSName[offset + 1] = sRDSToUnicodeMap[blocks[3] & 0xFF];
if (mPSNameState != 0xF) {
break;
}
mPSNameState = 0;
if (memcmp(mTempPSName, mPSName, sizeof(mTempPSName))) {
MutexAutoLock lock(mRDSLock);
mPSNameSet = true;
memcpy(mPSName, mTempPSName, sizeof(mTempPSName));
NS_DispatchToMainThread(new NotifyRunnable(PSChanged));
}
break;
}
case 4: // 2a Radiotext
{
uint16_t segmentAddr = (blocks[1] & 0xF);
bool textAB = blocks[1] & (1 << 5);
if (textAB != mRadiotextAB) {
mRadiotextState = 0;
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
mRadiotextAB = textAB;
MutexAutoLock lock(mRDSLock);
memset(mRadiotext, 0, sizeof(mRadiotext));
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
}
// mRadiotextState is a bitmask that lets us ensure all segments
// are received before updating the radiotext.
if (!segmentAddr) {
mRadiotextState = 1;
} else {
mRadiotextState |= 1 << segmentAddr;
}
uint8_t segment[4];
segment[0] = blocks[2] >> 8;
segment[1] = blocks[2] & 0xFF;
segment[2] = blocks[3] >> 8;
segment[3] = blocks[3] & 0xFF;
uint16_t offset = segmentAddr << 2;
bool done = false;
for (int i = 0; i < 4; i++) {
if (segment[i] == '\r') {
mTempRadiotext[offset++] = 0;
done = true;
} else {
mTempRadiotext[offset++] = sRDSToUnicodeMap[segment[i]];
}
}
if (offset == 64) {
done = true;
}
if (!done ||
(mRadiotextState + 1) != (1 << ((blocks[1] & 0xF) + 1)) ||
!memcmp(mTempRadiotext, mRadiotext, sizeof(mTempRadiotext))) {
break;
}
MutexAutoLock lock(mRDSLock);
mRadiotextSet = true;
memcpy(mRadiotext, mTempRadiotext, sizeof(mTempRadiotext));
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
break;
}
case 5: // 2b Radiotext
{
uint16_t segmentAddr = (blocks[1] & 0xF);
bool textAB = blocks[1] & (1 << 5);
if (textAB != mRadiotextAB) {
mRadiotextState = 0;
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
mRadiotextAB = textAB;
MutexAutoLock lock(mRDSLock);
memset(mRadiotext, 0, sizeof(mRadiotext));
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
}
if (!segmentAddr) {
mRadiotextState = 1;
} else {
mRadiotextState |= 1 << segmentAddr;
}
uint8_t segment[2];
segment[0] = blocks[3] >> 8;
segment[1] = blocks[3] & 0xFF;
uint16_t offset = segmentAddr << 1;
bool done = false;
for (int i = 0; i < 2; i++) {
if (segment[i] == '\r') {
mTempRadiotext[offset++] = 0;
done = true;
} else {
mTempRadiotext[offset++] = sRDSToUnicodeMap[segment[i]];
}
}
if (offset == 32) {
done = true;
}
if (!done ||
(mRadiotextState + 1) != (1 << ((blocks[1] & 0xF) + 1)) ||
!memcmp(mTempRadiotext, mRadiotext, sizeof(mTempRadiotext))) {
break;
}
MutexAutoLock lock(mRDSLock);
mRadiotextSet = true;
memcpy(mRadiotext, mTempRadiotext, sizeof(mTempRadiotext));
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
break;
}
case 31: // 15b Fast Tuning and Switching
{
uint16_t secondPty = (blocks[3] >> 5) & 0x1F;
if (pty == mPTY || pty != secondPty) {
break;
}
mPTY = pty;
NS_DispatchToMainThread(new NotifyRunnable(PTYChanged));
break;
}
}
// Only notify users of raw RDS groups that they're interested in.
// We always receive DOM_PARSED_RDS_GROUPS when RDS is enabled.
if (!(mRDSGroupMask & (1 << grouptype))) {
return;
}
uint64_t newgroup = blocks[0];
newgroup <<= 16;
newgroup |= blocks[1];
newgroup <<= 16;
newgroup |= blocks[2];
newgroup <<= 16;
newgroup |= blocks[3];
MutexAutoLock lock(mRDSLock);
mRDSGroup = newgroup;
mRDSGroupSet = true;
NS_DispatchToMainThread(new NotifyRunnable(NewRDSGroup));
}
void
FMRadioService::UpdatePowerState()
{
@ -802,6 +1210,13 @@ FMRadioService::UpdateFrequency()
if (mPendingFrequencyInKHz != frequency) {
mPendingFrequencyInKHz = frequency;
NotifyFMRadioEvent(FrequencyChanged);
mPISet = false;
mPTYSet = false;
memset(mPSName, 0, sizeof(mPSName));
memset(mRadiotext, 0, sizeof(mRadiotext));
mRDSGroupSet = false;
mPSNameSet = false;
mRadiotextSet = false;
}
}

View File

@ -7,9 +7,11 @@
#ifndef mozilla_dom_fmradioservice_h__
#define mozilla_dom_fmradioservice_h__
#include "mozilla/dom/Nullable.h"
#include "mozilla/dom/PFMRadioRequest.h"
#include "FMRadioCommon.h"
#include "mozilla/Hal.h"
#include "mozilla/Mutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Services.h"
#include "nsThreadUtils.h"
@ -95,10 +97,16 @@ protected:
public:
virtual bool IsEnabled() const = 0;
virtual bool IsRDSEnabled() const = 0;
virtual double GetFrequency() const = 0;
virtual double GetFrequencyUpperBound() const = 0;
virtual double GetFrequencyLowerBound() const = 0;
virtual double GetChannelWidth() const = 0;
virtual Nullable<unsigned short> GetPi() const = 0;
virtual Nullable<uint8_t> GetPty() const = 0;
virtual bool GetPs(nsString& aPsname) = 0;
virtual bool GetRt(nsString& aRadiotext) = 0;
virtual bool GetRdsgroup(uint64_t& aRDSGroup) = 0;
virtual void Enable(double aFrequency, FMRadioReplyRunnable* aReplyRunnable) = 0;
virtual void Disable(FMRadioReplyRunnable* aReplyRunnable) = 0;
@ -106,6 +114,9 @@ public:
virtual void Seek(mozilla::hal::FMRadioSeekDirection aDirection,
FMRadioReplyRunnable* aReplyRunnable) = 0;
virtual void CancelSeek(FMRadioReplyRunnable* aReplyRunnable) = 0;
virtual void SetRDSGroupMask(uint32_t aRDSGroupMask) = 0;
virtual void EnableRDS(FMRadioReplyRunnable* aReplyRunnable) = 0;
virtual void DisableRDS(FMRadioReplyRunnable* aReplyRunnable) = 0;
/**
* Register handler to receive the FM Radio events, including:
@ -138,11 +149,13 @@ enum FMRadioState
class FMRadioService MOZ_FINAL : public IFMRadioService
, public hal::FMRadioObserver
, public hal::FMRadioRDSObserver
, public nsIObserver
{
friend class ReadAirplaneModeSettingTask;
friend class EnableRunnable;
friend class DisableRunnable;
friend class NotifyRunnable;
public:
static FMRadioService* Singleton();
@ -151,10 +164,16 @@ public:
NS_DECL_ISUPPORTS
virtual bool IsEnabled() const MOZ_OVERRIDE;
virtual bool IsRDSEnabled() const MOZ_OVERRIDE;
virtual double GetFrequency() const MOZ_OVERRIDE;
virtual double GetFrequencyUpperBound() const MOZ_OVERRIDE;
virtual double GetFrequencyLowerBound() const MOZ_OVERRIDE;
virtual double GetChannelWidth() const MOZ_OVERRIDE;
virtual Nullable<unsigned short> GetPi() const MOZ_OVERRIDE;
virtual Nullable<uint8_t> GetPty() const MOZ_OVERRIDE;
virtual bool GetPs(nsString& aPsname) MOZ_OVERRIDE;
virtual bool GetRt(nsString& aRadiotext) MOZ_OVERRIDE;
virtual bool GetRdsgroup(uint64_t& aRDSGroup) MOZ_OVERRIDE;
virtual void Enable(double aFrequency,
FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
@ -164,6 +183,9 @@ public:
virtual void Seek(mozilla::hal::FMRadioSeekDirection aDirection,
FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
virtual void CancelSeek(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
virtual void SetRDSGroupMask(uint32_t aRDSGroupMask) MOZ_OVERRIDE;
virtual void EnableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
virtual void DisableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
virtual void AddObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
virtual void RemoveObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
@ -172,6 +194,8 @@ public:
/* FMRadioObserver */
void Notify(const hal::FMRadioOperationInformation& aInfo) MOZ_OVERRIDE;
/* FMRadioRDSObserver */
void Notify(const hal::FMRadioRDSGroup& aRDSGroup) MOZ_OVERRIDE;
NS_DECL_NSIOBSERVER
@ -197,6 +221,7 @@ private:
bool mHasReadAirplaneModeSetting;
bool mAirplaneModeEnabled;
bool mRDSEnabled;
uint32_t mUpperBoundInKHz;
uint32_t mLowerBoundInKHz;
@ -209,6 +234,30 @@ private:
FMRadioEventObserverList mObserverList;
static StaticRefPtr<FMRadioService> sFMRadioService;
uint32_t mRDSGroupMask;
uint16_t mLastPI;
uint16_t mLastPTY;
Atomic<uint32_t> mPI;
Atomic<uint32_t> mPTY;
Atomic<bool> mPISet;
Atomic<bool> mPTYSet;
/* Protects mPSName, mRadiotext, and mRDSGroup */
Mutex mRDSLock;
char16_t mPSName[9];
char16_t mRadiotext[65];
uint64_t mRDSGroup;
uint8_t mPSNameState;
uint16_t mRadiotextState;
uint16_t mTempPSName[8];
uint16_t mTempRadiotext[64];
bool mRadiotextAB;
bool mRDSGroupSet;
bool mPSNameSet;
bool mRadiotextSet;
};
END_FMRADIO_NAMESPACE

View File

@ -16,7 +16,13 @@ StaticAutoPtr<FMRadioChild> FMRadioChild::sFMRadioChild;
FMRadioChild::FMRadioChild()
: mEnabled(false)
, mRDSEnabled(false)
, mRDSGroupSet(false)
, mPSNameSet(false)
, mRadiotextSet(false)
, mFrequency(0)
, mRDSGroup(0)
, mRDSGroupMask(0)
, mObserverList(FMRadioEventObserverList())
{
MOZ_COUNT_CTOR(FMRadioChild);
@ -44,6 +50,12 @@ FMRadioChild::IsEnabled() const
return mEnabled;
}
bool
FMRadioChild::IsRDSEnabled() const
{
return mRDSEnabled;
}
double
FMRadioChild::GetFrequency() const
{
@ -69,6 +81,43 @@ FMRadioChild::GetChannelWidth() const
return mChannelWidth;
}
Nullable<unsigned short>
FMRadioChild::GetPi() const
{
return mPI;
}
Nullable<uint8_t>
FMRadioChild::GetPty() const
{
return mPTY;
}
bool
FMRadioChild::GetPs(nsString& aPSName)
{
if (mPSNameSet) {
aPSName = mPSName;
}
return mPSNameSet;
}
bool
FMRadioChild::GetRt(nsString& aRadiotext)
{
if (mRadiotextSet) {
aRadiotext = mRadiotext;
}
return mRadiotextSet;
}
bool
FMRadioChild::GetRdsgroup(uint64_t& aRDSGroup)
{
aRDSGroup = mRDSGroup;
return mRDSGroupSet;
}
void
FMRadioChild::Enable(double aFrequency, FMRadioReplyRunnable* aReplyRunnable)
{
@ -101,6 +150,25 @@ FMRadioChild::CancelSeek(FMRadioReplyRunnable* aReplyRunnable)
SendRequest(aReplyRunnable, CancelSeekRequestArgs());
}
void
FMRadioChild::SetRDSGroupMask(uint32_t aRDSGroupMask)
{
mRDSGroupMask = aRDSGroupMask;
SendSetRDSGroupMask(aRDSGroupMask);
}
void
FMRadioChild::EnableRDS(FMRadioReplyRunnable* aReplyRunnable)
{
SendRequest(aReplyRunnable, EnableRDSArgs());
}
void
FMRadioChild::DisableRDS(FMRadioReplyRunnable* aReplyRunnable)
{
SendRequest(aReplyRunnable, DisableRDSArgs());
}
inline void
FMRadioChild::NotifyFMRadioEvent(FMRadioEventType aType)
{
@ -132,6 +200,26 @@ FMRadioChild::RecvNotifyFrequencyChanged(const double& aFrequency)
{
mFrequency = aFrequency;
NotifyFMRadioEvent(FrequencyChanged);
if (!mPI.IsNull()) {
mPI.SetNull();
NotifyFMRadioEvent(PIChanged);
}
if (!mPTY.IsNull()) {
mPTY.SetNull();
NotifyFMRadioEvent(PTYChanged);
}
if (mPSNameSet) {
mPSNameSet = false;
mPSName.Truncate();
NotifyFMRadioEvent(PSChanged);
}
if (mRadiotextSet) {
mRadiotextSet = false;
mRadiotext.Truncate();
NotifyFMRadioEvent(RadiotextChanged);
}
mRDSGroupSet = false;
return true;
}
@ -141,10 +229,85 @@ FMRadioChild::RecvNotifyEnabledChanged(const bool& aEnabled,
{
mEnabled = aEnabled;
mFrequency = aFrequency;
if (!mEnabled) {
mPI.SetNull();
mPTY.SetNull();
mPSName.Truncate();
mRadiotext.Truncate();
mRDSGroupSet = false;
mPSNameSet = false;
mRadiotextSet = false;
}
NotifyFMRadioEvent(EnabledChanged);
return true;
}
bool
FMRadioChild::RecvNotifyRDSEnabledChanged(const bool& aEnabled)
{
mRDSEnabled = aEnabled;
NotifyFMRadioEvent(RDSEnabledChanged);
return true;
}
bool
FMRadioChild::RecvNotifyPIChanged(const bool& aValid,
const uint16_t& aCode)
{
if (aValid) {
mPI.SetValue(aCode);
} else {
mPI.SetNull();
}
NotifyFMRadioEvent(PIChanged);
return true;
}
bool
FMRadioChild::RecvNotifyPTYChanged(const bool& aValid,
const uint8_t& aPTY)
{
if (aValid) {
mPTY.SetValue(aPTY);
} else {
mPTY.SetNull();
}
NotifyFMRadioEvent(PTYChanged);
return true;
}
bool
FMRadioChild::RecvNotifyPSChanged(const nsString& aPSName)
{
mPSNameSet = true;
mPSName = aPSName;
NotifyFMRadioEvent(PSChanged);
return true;
}
bool
FMRadioChild::RecvNotifyRadiotextChanged(const nsString& aRadiotext)
{
mRadiotextSet = true;
mRadiotext = aRadiotext;
NotifyFMRadioEvent(RadiotextChanged);
return true;
}
bool
FMRadioChild::RecvNotifyNewRDSGroup(const uint64_t& aGroup)
{
uint16_t grouptype = (aGroup >> 43) & 0x1F;
if (!(mRDSGroupMask & (1 << grouptype))) {
return true;
}
mRDSGroupSet = true;
mRDSGroup = aGroup;
NotifyFMRadioEvent(NewRDSGroup);
return true;
}
bool
FMRadioChild::Recv__delete__()
{

View File

@ -34,10 +34,16 @@ public:
/* IFMRadioService */
virtual bool IsEnabled() const MOZ_OVERRIDE;
virtual bool IsRDSEnabled() const MOZ_OVERRIDE;
virtual double GetFrequency() const MOZ_OVERRIDE;
virtual double GetFrequencyUpperBound() const MOZ_OVERRIDE;
virtual double GetFrequencyLowerBound() const MOZ_OVERRIDE;
virtual double GetChannelWidth() const MOZ_OVERRIDE;
virtual Nullable<unsigned short> GetPi() const MOZ_OVERRIDE;
virtual Nullable<uint8_t> GetPty() const MOZ_OVERRIDE;
virtual bool GetPs(nsString& aPSName) MOZ_OVERRIDE;
virtual bool GetRt(nsString& aRadiotext) MOZ_OVERRIDE;
virtual bool GetRdsgroup(uint64_t& aRDSGroup) MOZ_OVERRIDE;
virtual void Enable(double aFrequency,
FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
@ -47,6 +53,9 @@ public:
virtual void Seek(mozilla::hal::FMRadioSeekDirection aDirection,
FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
virtual void CancelSeek(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
virtual void SetRDSGroupMask(uint32_t aRDSGroupMask) MOZ_OVERRIDE;
virtual void EnableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
virtual void DisableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
virtual void AddObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
virtual void RemoveObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
@ -64,6 +73,26 @@ public:
RecvNotifyEnabledChanged(const bool& aEnabled,
const double& aFrequency) MOZ_OVERRIDE;
virtual bool
RecvNotifyRDSEnabledChanged(const bool& aEnabled) MOZ_OVERRIDE;
virtual bool
RecvNotifyPIChanged(const bool& aValid,
const uint16_t& aCode) MOZ_OVERRIDE;
virtual bool
RecvNotifyPTYChanged(const bool& aValid,
const uint8_t& aPTY) MOZ_OVERRIDE;
virtual bool
RecvNotifyPSChanged(const nsString& aPSName) MOZ_OVERRIDE;
virtual bool
RecvNotifyRadiotextChanged(const nsString& aRadiotext) MOZ_OVERRIDE;
virtual bool
RecvNotifyNewRDSGroup(const uint64_t& aGroup) MOZ_OVERRIDE;
virtual PFMRadioRequestChild*
AllocPFMRadioRequestChild(const FMRadioRequestArgs& aArgs) MOZ_OVERRIDE;
@ -78,10 +107,20 @@ private:
inline void NotifyFMRadioEvent(FMRadioEventType aType);
bool mEnabled;
bool mRDSEnabled;
bool mRDSGroupSet;
bool mPSNameSet;
bool mRadiotextSet;
double mFrequency;
double mUpperBound;
double mLowerBound;
double mChannelWidth;
Nullable<unsigned short> mPI;
Nullable<uint8_t> mPTY;
nsAutoString mPSName;
nsAutoString mRadiotext;
uint64_t mRDSGroup;
uint32_t mRDSGroupMask;
FMRadioEventObserverList mObserverList;

View File

@ -6,6 +6,7 @@
#include "FMRadioParent.h"
#include "mozilla/unused.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/DebugOnly.h"
#include "FMRadioRequestParent.h"
#include "FMRadioService.h"
@ -69,6 +70,12 @@ FMRadioParent::AllocPFMRadioRequestParent(const FMRadioRequestArgs& aArgs)
case FMRadioRequestArgs::TCancelSeekRequestArgs:
IFMRadioService::Singleton()->CancelSeek(requestParent);
break;
case FMRadioRequestArgs::TEnableRDSArgs:
IFMRadioService::Singleton()->EnableRDS(requestParent);
break;
case FMRadioRequestArgs::TDisableRDSArgs:
IFMRadioService::Singleton()->DisableRDS(requestParent);
break;
default:
MOZ_CRASH();
}
@ -98,6 +105,43 @@ FMRadioParent::Notify(const FMRadioEventType& aType)
IFMRadioService::Singleton()->IsEnabled(),
IFMRadioService::Singleton()->GetFrequency());
break;
case RDSEnabledChanged:
unused << SendNotifyRDSEnabledChanged(
IFMRadioService::Singleton()->IsRDSEnabled());
break;
case PIChanged: {
Nullable<unsigned short> pi =
IFMRadioService::Singleton()->GetPi();
unused << SendNotifyPIChanged(!pi.IsNull(),
pi.IsNull() ? 0 : pi.Value());
break;
}
case PTYChanged: {
Nullable<uint8_t> pty = IFMRadioService::Singleton()->GetPty();
unused << SendNotifyPTYChanged(!pty.IsNull(),
pty.IsNull() ? 0 : pty.Value());
break;
}
case PSChanged: {
nsAutoString psname;
IFMRadioService::Singleton()->GetPs(psname);
unused << SendNotifyPSChanged(psname);
break;
}
case RadiotextChanged: {
nsAutoString radiotext;
IFMRadioService::Singleton()->GetRt(radiotext);
unused << SendNotifyRadiotextChanged(radiotext);
break;
}
case NewRDSGroup: {
uint64_t group;
DebugOnly<bool> rdsgroupset =
IFMRadioService::Singleton()->GetRdsgroup(group);
MOZ_ASSERT(rdsgroupset);
unused << SendNotifyNewRDSGroup(group);
break;
}
default:
NS_RUNTIMEABORT("not reached");
break;
@ -111,5 +155,12 @@ FMRadioParent::RecvEnableAudio(const bool& aAudioEnabled)
return true;
}
bool
FMRadioParent::RecvSetRDSGroupMask(const uint32_t& aRDSGroupMask)
{
IFMRadioService::Singleton()->SetRDSGroupMask(aRDSGroupMask);
return true;
}
END_FMRADIO_NAMESPACE

View File

@ -39,6 +39,9 @@ public:
virtual bool
RecvEnableAudio(const bool& aAudioEnabled) MOZ_OVERRIDE;
virtual bool
RecvSetRDSGroupMask(const uint32_t& aRDSGroupMask) MOZ_OVERRIDE;
};
END_FMRADIO_NAMESPACE

View File

@ -34,6 +34,14 @@ struct CancelSeekRequestArgs
{
};
struct EnableRDSArgs
{
};
struct DisableRDSArgs
{
};
union FMRadioRequestArgs
{
EnableRequestArgs;
@ -41,6 +49,8 @@ union FMRadioRequestArgs
SetFrequencyRequestArgs;
SeekRequestArgs;
CancelSeekRequestArgs;
EnableRDSArgs;
DisableRDSArgs;
};
struct StatusInfo
@ -66,6 +76,30 @@ child:
* Sent when the power state of FM radio HW is changed.
*/
NotifyEnabledChanged(bool enabled, double frequency);
/**
* Sent when RDS is enabled or disabled.
*/
NotifyRDSEnabledChanged(bool enabled);
/**
* Sent when we have a new PI code.
*/
NotifyPIChanged(bool valid, uint16_t code);
/**
* Sent when we have a new PTY
*/
NotifyPTYChanged(bool valid, uint8_t pty);
/**
* Sent when we have a new PS name.
*/
NotifyPSChanged(nsString psname);
/**
* Sent when we have new radiotext.
*/
NotifyRadiotextChanged(nsString radiotext);
/**
* Sent when a full RDS group is received.
*/
NotifyNewRDSGroup(uint64_t data);
__delete__();
@ -91,6 +125,11 @@ parent:
* Enable/Disable audio
*/
EnableAudio(bool audioEnabled);
/**
* Set RDS group mask
*/
SetRDSGroupMask(uint32_t groupMask);
};
} // namespace dom

View File

@ -482,7 +482,7 @@ NetworkManager.prototype = {
return Promise.reject("Invalid network interface.");
}
return this.resolveHostname(host)
return this.resolveHostname(network, host)
.then((ipAddresses) => this._updateRoutes(true,
ipAddresses,
network.name,
@ -494,7 +494,7 @@ NetworkManager.prototype = {
return Promise.reject("Invalid network interface.");
}
return this.resolveHostname(host)
return this.resolveHostname(network, host)
.then((ipAddresses) => this._updateRoutes(false,
ipAddresses,
network.name,
@ -594,7 +594,7 @@ NetworkManager.prototype = {
// The override was just set, so reconfigure the network.
if (this.active != this._overriddenActive) {
this.active = this._overriddenActive;
gNetworkService.setDefaultRouteAndDNS(this.active, oldActive);
this._setDefaultRouteAndDNS(this.active, oldActive);
Services.obs.notifyObservers(this.active, TOPIC_ACTIVE_CHANGED, null);
}
return;
@ -605,7 +605,7 @@ NetworkManager.prototype = {
this.active.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED &&
this.active.type == this._preferredNetworkType) {
debug("Active network is already our preferred type.");
gNetworkService.setDefaultRouteAndDNS(this.active, oldActive);
this._setDefaultRouteAndDNS(this.active, oldActive);
return;
}
@ -641,10 +641,10 @@ NetworkManager.prototype = {
}
// Don't set default route on secondary APN
if (this.isNetworkTypeSecondaryMobile(this.active.type)) {
gNetworkService.setDNS(this.active);
gNetworkService.setDNS(this.active, function() {});
} else {
#endif // MOZ_B2G_RIL
gNetworkService.setDefaultRouteAndDNS(this.active, oldActive);
this._setDefaultRouteAndDNS(this.active, oldActive);
#ifdef MOZ_B2G_RIL
}
#endif
@ -659,7 +659,7 @@ NetworkManager.prototype = {
}
},
resolveHostname: function(hostname) {
resolveHostname: function(network, hostname) {
// Sanity check for null, undefined and empty string... etc.
if (!hostname) {
return Promise.reject(new Error("hostname is empty: " + hostname));
@ -694,8 +694,18 @@ NetworkManager.prototype = {
deferred.resolve(retval);
};
// Bug 1058282 - Explicitly request ipv4 to get around 8.8.8.8 probe at
// http://androidxref.com/4.3_r2.1/xref/bionic/libc/netbsd/net/getaddrinfo.c#1923
//
// Whenever MMS connection is the only network interface, there is no
// default route so that any ip probe will fail.
let flags = 0;
if (network.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) {
flags |= Ci.nsIDNSService.RESOLVE_DISABLE_IPV6;
}
// TODO: Bug 992772 - Resolve the hostname with specified networkInterface.
gDNSService.asyncResolve(hostname, 0, onLookupComplete, Services.tm.mainThread);
gDNSService.asyncResolve(hostname, flags, onLookupComplete, Services.tm.mainThread);
return deferred.promise;
},
@ -1297,7 +1307,15 @@ NetworkManager.prototype = {
this.wantConnectionEvent = null;
callback.call(this);
}
},
_setDefaultRouteAndDNS: function(network, oldInterface) {
gNetworkService.setDefaultRoute(network, oldInterface, function(success) {
gNetworkService.setDNS(network, function(result) {
gNetworkService.setNetworkProxy(network);
});
});
},
};
let CaptivePortalDetectionHelper = (function() {

View File

@ -188,7 +188,6 @@ NetworkService.prototype = {
};
params.report = true;
params.isAsync = true;
this.controlMessage(params, function(result) {
if (!isError(result.resultCode)) {
@ -210,7 +209,6 @@ NetworkService.prototype = {
};
params.report = true;
params.isAsync = true;
this.controlMessage(params, function(result) {
if (!isError(result.resultCode)) {
@ -230,7 +228,6 @@ NetworkService.prototype = {
};
params.report = true;
params.isAsync = true;
this.controlMessage(params, function(result) {
callback(result);
@ -247,7 +244,6 @@ NetworkService.prototype = {
};
params.report = true;
params.isAsync = true;
this.controlMessage(params, function(result) {
if (isError(result.resultCode)) {
@ -277,8 +273,8 @@ NetworkService.prototype = {
}
},
setDNS: function(networkInterface) {
if(DEBUG) debug("Going DNS to " + networkInterface.name);
setDNS: function(networkInterface, callback) {
if (DEBUG) debug("Going DNS to " + networkInterface.name);
let dnses = networkInterface.getDnses();
let options = {
cmd: "setDNS",
@ -286,23 +282,23 @@ NetworkService.prototype = {
domain: "mozilla." + networkInterface.name + ".doman",
dnses: dnses
};
this.controlMessage(options);
this.controlMessage(options, function(result) {
callback.setDnsResult(result.success ? null : result.reason);
});
},
setDefaultRouteAndDNS: function(network, oldInterface) {
if(DEBUG) debug("Going to change route and DNS to " + network.name);
setDefaultRoute: function(network, oldInterface, callback) {
if (DEBUG) debug("Going to change default route to " + network.name);
let gateways = network.getGateways();
let dnses = network.getDnses();
let options = {
cmd: "setDefaultRouteAndDNS",
cmd: "setDefaultRoute",
ifname: network.name,
oldIfname: (oldInterface && oldInterface !== network) ? oldInterface.name : null,
gateways: gateways,
domain: "mozilla." + network.name + ".doman",
dnses: dnses
gateways: gateways
};
this.controlMessage(options);
this.setNetworkProxy(network);
this.controlMessage(options, function(result) {
callback.nativeCommandResult(!result.error);
});
},
removeDefaultRoute: function(network) {
@ -415,7 +411,6 @@ NetworkService.prototype = {
}
config.cmd = "setDhcpServer";
config.isAsync = true;
config.enabled = enabled;
this.controlMessage(config, function setDhcpServerResult(response) {
@ -437,7 +432,6 @@ NetworkService.prototype = {
config.cmd = "setWifiTethering";
// The callback function in controlMessage may not be fired immediately.
config.isAsync = true;
this.controlMessage(config, function setWifiTetheringResult(data) {
let code = data.resultCode;
let reason = data.resultReason;
@ -458,7 +452,6 @@ NetworkService.prototype = {
setUSBTethering: function(enable, config, callback) {
config.cmd = "setUSBTethering";
// The callback function in controlMessage may not be fired immediately.
config.isAsync = true;
this.controlMessage(config, function setUsbTetheringResult(data) {
let code = data.resultCode;
let reason = data.resultReason;
@ -491,7 +484,6 @@ NetworkService.prototype = {
}
// The callback function in controlMessage may not be fired immediately.
params.isAsync = true;
//this._usbTetheringAction = TETHERING_STATE_ONGOING;
this.controlMessage(params, function(data) {
callback.enableUsbRndisResult(data.result, data.enable);
@ -501,7 +493,6 @@ NetworkService.prototype = {
updateUpStream: function(previous, current, callback) {
let params = {
cmd: "updateUpStream",
isAsync: true,
preInternalIfname: previous.internalIfname,
preExternalIfname: previous.externalIfname,
curInternalIfname: current.internalIfname,
@ -516,6 +507,66 @@ NetworkService.prototype = {
});
},
configureInterface: function(config, callback) {
let params = {
cmd: "configureInterface",
ifname: config.ifname,
ipaddr: config.ipaddr,
mask: config.mask,
gateway_long: config.gateway,
dns1_long: config.dns1,
dns2_long: config.dns2,
};
this.controlMessage(params, function(result) {
callback.nativeCommandResult(!result.error);
});
},
dhcpRequest: function(interfaceName, callback) {
let params = {
cmd: "dhcpRequest",
ifname: interfaceName
};
this.controlMessage(params, function(result) {
callback.dhcpRequestResult(!result.error, result.error ? null : result);
});
},
enableInterface: function(interfaceName, callback) {
let params = {
cmd: "enableInterface",
ifname: interfaceName
};
this.controlMessage(params, function(result) {
callback.nativeCommandResult(!result.error);
});
},
disableInterface: function(interfaceName, callback) {
let params = {
cmd: "disableInterface",
ifname: interfaceName
};
this.controlMessage(params, function(result) {
callback.nativeCommandResult(!result.error);
});
},
resetConnections: function(interfaceName, callback) {
let params = {
cmd: "resetConnections",
ifname: interfaceName
};
this.controlMessage(params, function(result) {
callback.nativeCommandResult(!result.error);
});
},
shutdown: false,
observe: function observe(aSubject, aTopic, aData) {

View File

@ -101,7 +101,14 @@ typedef Tuple3<NetdCommand*, CommandChain*, CommandCallback> QueueData;
#define GET_CURRENT_CALLBACK (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].c)
#define GET_CURRENT_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a->mData)
#define CNT_OF_ARRAY(a) (sizeof(a) / sizeof(a[0]))
// A macro for native function call return value check.
// For native function call, non-zero return value means failure.
#define RETURN_IF_FAILED(rv) do { \
if (SUCCESS != rv) { \
return rv; \
} \
} while (0);
static NetworkUtils* gNetworkUtils;
static nsTArray<QueueData> gCommandQueue;
@ -393,6 +400,40 @@ void NetworkUtils::next(CommandChain* aChain, bool aError, NetworkResultOptions&
(*f)(aChain, next, aResult);
}
CommandResult::CommandResult(int32_t aResultCode)
: mIsPending(false)
{
// This is usually not a netd command. We treat the return code
// typical linux convention, which uses 0 to indicate success.
mResult.mError = (aResultCode == SUCCESS ? false : true);
mResult.mResultCode = aResultCode;
if (aResultCode != SUCCESS) {
// The returned value is sometimes negative, make sure we pass a positive
// error number to strerror.
enum { STRERROR_R_BUF_SIZE = 1024, };
char strerrorBuf[STRERROR_R_BUF_SIZE];
strerror_r(abs(aResultCode), strerrorBuf, STRERROR_R_BUF_SIZE);
mResult.mReason = NS_ConvertUTF8toUTF16(strerrorBuf);
}
mResult.mRet = true;
}
CommandResult::CommandResult(const mozilla::dom::NetworkResultOptions& aResult)
: mResult(aResult)
, mIsPending(false)
{
}
CommandResult::CommandResult(const Pending&)
: mIsPending(true)
{
}
bool CommandResult::isPending() const
{
return mIsPending;
}
/**
* Send command to netd.
*/
@ -1030,14 +1071,19 @@ NetworkUtils::~NetworkUtils()
#define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aOptions.prop).get()
#define GET_FIELD(prop) aOptions.prop
// Hoist this type definition to global to avoid template
// instantiation error on gcc 4.4 used by ICS emulator.
typedef CommandResult (NetworkUtils::*CommandHandler)(NetworkParams&);
struct CommandHandlerEntry
{
const char* mCommandName;
CommandHandler mCommandHandler;
};
void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
{
typedef int32_t (NetworkUtils::*CommandHandler)(NetworkParams&);
const static struct {
const char* mCommandName;
CommandHandler mCommandHandler;
} COMMAND_HANDLER_TABLE[] = {
const static CommandHandlerEntry
COMMAND_HANDLER_TABLE[] = {
// For command 'testCommand', BUILD_ENTRY(testCommand) will generate
// {"testCommand", NetworkUtils::testCommand}
@ -1045,7 +1091,7 @@ void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
BUILD_ENTRY(removeNetworkRoute),
BUILD_ENTRY(setDNS),
BUILD_ENTRY(setDefaultRouteAndDNS),
BUILD_ENTRY(setDefaultRoute),
BUILD_ENTRY(removeDefaultRoute),
BUILD_ENTRY(addHostRoute),
BUILD_ENTRY(removeHostRoute),
@ -1061,13 +1107,18 @@ void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
BUILD_ENTRY(setUSBTethering),
BUILD_ENTRY(enableUsbRndis),
BUILD_ENTRY(updateUpStream),
BUILD_ENTRY(configureInterface),
BUILD_ENTRY(dhcpRequest),
BUILD_ENTRY(enableInterface),
BUILD_ENTRY(disableInterface),
BUILD_ENTRY(resetConnections),
#undef BUILD_ENTRY
};
// Loop until we find the command name which matches aOptions.mCmd.
CommandHandler handler = nullptr;
for (size_t i = 0; i < CNT_OF_ARRAY(COMMAND_HANDLER_TABLE); i++) {
for (size_t i = 0; i < mozilla::ArrayLength(COMMAND_HANDLER_TABLE); i++) {
if (aOptions.mCmd.EqualsASCII(COMMAND_HANDLER_TABLE[i].mCommandName)) {
handler = COMMAND_HANDLER_TABLE[i].mCommandHandler;
break;
@ -1080,25 +1131,19 @@ void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
return;
}
// Command matches! Dispatch to the handler.
int32_t ret = 0;
ret = (this->*handler)(aOptions);
if (!aOptions.mIsAsync) {
// The requested command is synchronous, which implies the actual result
// from netd is not important to the client. So, just notify the
// registered callback.
NetworkResultOptions result;
result.mError = ret == SUCCESS ? false : true;
result.mResultCode = ret;
if (ret != SUCCESS) {
// The returned value is sometimes negative, make sure we pass a positive
// error number to strerror.
result.mReason = NS_ConvertUTF8toUTF16(strerror(abs(ret)));
}
result.mRet = true;
postMessage(aOptions, result);
// The handler would return one of the following 3 values
// to be wrapped to CommandResult:
//
// 1) |int32_t| for mostly synchronous native function calls.
// 2) |NetworkResultOptions| to populate additional results. (e.g. dhcpRequest)
// 3) |CommandResult::Pending| to indicate the result is not
// obtained yet.
//
// If the handler returns "Pending", the handler should take the
// responsibility for posting result to main thread.
CommandResult commandResult = (this->*handler)(aOptions);
if (!commandResult.isPending()) {
postMessage(aOptions, commandResult.mResult);
}
}
@ -1183,7 +1228,7 @@ void NetworkUtils::onNetdMessage(NetdCommand* aCommand)
/**
* Start/Stop DHCP server.
*/
int32_t NetworkUtils::setDhcpServer(NetworkParams& aOptions)
CommandResult NetworkUtils::setDhcpServer(NetworkParams& aOptions)
{
if (aOptions.mEnabled) {
aOptions.mWifiStartIp = aOptions.mStartIp;
@ -1196,13 +1241,13 @@ int32_t NetworkUtils::setDhcpServer(NetworkParams& aOptions)
} else {
RUN_CHAIN(aOptions, sStopDhcpServerChain, setDhcpServerFail)
}
return SUCCESS;
return CommandResult::Pending();
}
/**
* Set DNS servers for given network interface.
*/
int32_t NetworkUtils::setDNS(NetworkParams& aOptions)
CommandResult NetworkUtils::setDNS(NetworkParams& aOptions)
{
uint32_t length = aOptions.mDnses.Length();
@ -1234,23 +1279,116 @@ int32_t NetworkUtils::setDNS(NetworkParams& aOptions)
// DNS needs to be set through netd since JellyBean (4.3).
if (SDK_VERSION >= 18) {
RUN_CHAIN(aOptions, sSetDnsChain, setDnsFail)
return CommandResult::Pending();
}
return SUCCESS;
}
CommandResult NetworkUtils::configureInterface(NetworkParams& aOptions)
{
NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
return mNetUtils->do_ifc_configure(
autoIfname.get(),
aOptions.mIpaddr,
aOptions.mMask,
aOptions.mGateway_long,
aOptions.mDns1_long,
aOptions.mDns2_long
);
}
CommandResult NetworkUtils::dhcpRequest(NetworkParams& aOptions) {
mozilla::dom::NetworkResultOptions result;
NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
char ipaddr[PROPERTY_VALUE_MAX];
char gateway[PROPERTY_VALUE_MAX];
uint32_t prefixLength;
char dns1[PROPERTY_VALUE_MAX];
char dns2[PROPERTY_VALUE_MAX];
char server[PROPERTY_VALUE_MAX];
uint32_t lease;
char vendorinfo[PROPERTY_VALUE_MAX];
int32_t ret = mNetUtils->do_dhcp_do_request(autoIfname.get(),
ipaddr,
gateway,
&prefixLength,
dns1,
dns2,
server,
&lease,
vendorinfo);
RETURN_IF_FAILED(ret);
result.mIpaddr_str = NS_ConvertUTF8toUTF16(ipaddr);
result.mGateway_str = NS_ConvertUTF8toUTF16(gateway);
result.mDns1_str = NS_ConvertUTF8toUTF16(dns1);
result.mDns2_str = NS_ConvertUTF8toUTF16(dns2);
result.mServer_str = NS_ConvertUTF8toUTF16(server);
result.mVendor_str = NS_ConvertUTF8toUTF16(vendorinfo);
result.mLease = lease;
result.mMask = makeMask(prefixLength);
uint32_t inet4; // only support IPv4 for now.
#define INET_PTON(var, field) \
PR_BEGIN_MACRO \
inet_pton(AF_INET, var, &inet4); \
result.field = inet4; \
PR_END_MACRO
INET_PTON(ipaddr, mIpaddr);
INET_PTON(gateway, mGateway);
if (dns1[0] != '\0') {
INET_PTON(dns1, mDns1);
}
if (dns2[0] != '\0') {
INET_PTON(dns2, mDns2);
}
INET_PTON(server, mServer);
char inet_str[64];
if (inet_ntop(AF_INET, &result.mMask, inet_str, sizeof(inet_str))) {
result.mMask_str = NS_ConvertUTF8toUTF16(inet_str);
}
return result;
}
CommandResult NetworkUtils::enableInterface(NetworkParams& aOptions) {
return mNetUtils->do_ifc_enable(
NS_ConvertUTF16toUTF8(aOptions.mIfname).get());
}
CommandResult NetworkUtils::disableInterface(NetworkParams& aOptions) {
return mNetUtils->do_ifc_disable(
NS_ConvertUTF16toUTF8(aOptions.mIfname).get());
}
CommandResult NetworkUtils::resetConnections(NetworkParams& aOptions) {
NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
return mNetUtils->do_ifc_reset_connections(
NS_ConvertUTF16toUTF8(aOptions.mIfname).get(),
RESET_ALL_ADDRESSES);
}
/**
* Set default route and DNS servers for given network interface.
*/
int32_t NetworkUtils::setDefaultRouteAndDNS(NetworkParams& aOptions)
CommandResult NetworkUtils::setDefaultRoute(NetworkParams& aOptions)
{
NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
if (!aOptions.mOldIfname.IsEmpty()) {
// Remove IPv4's default route.
mNetUtils->do_ifc_remove_default_route(GET_CHAR(mOldIfname));
RETURN_IF_FAILED(mNetUtils->do_ifc_remove_default_route(GET_CHAR(mOldIfname)));
// Remove IPv6's default route.
mNetUtils->do_ifc_remove_route(GET_CHAR(mOldIfname), "::", 0, NULL);
RETURN_IF_FAILED(mNetUtils->do_ifc_remove_route(GET_CHAR(mOldIfname), "::", 0, NULL));
}
uint32_t length = aOptions.mGateways.Length();
@ -1264,9 +1402,9 @@ int32_t NetworkUtils::setDefaultRouteAndDNS(NetworkParams& aOptions)
}
if (type == AF_INET6) {
mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, autoGateway.get());
RETURN_IF_FAILED(mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, autoGateway.get()));
} else { /* type == AF_INET */
mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(autoGateway.get()));
RETURN_IF_FAILED(mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(autoGateway.get())));
}
}
} else {
@ -1283,20 +1421,19 @@ int32_t NetworkUtils::setDefaultRouteAndDNS(NetworkParams& aOptions)
}
if (type == AF_INET6) {
mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, gateway);
RETURN_IF_FAILED(mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, gateway));
} else { /* type == AF_INET */
mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(gateway));
RETURN_IF_FAILED(mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(gateway)));
}
}
setDNS(aOptions);
return SUCCESS;
}
/**
* Remove default route for given network interface.
*/
int32_t NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
CommandResult NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
{
uint32_t length = aOptions.mGateways.Length();
for (uint32_t i = 0; i < length; i++) {
@ -1307,9 +1444,9 @@ int32_t NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
return EAFNOSUPPORT;
}
mNetUtils->do_ifc_remove_route(GET_CHAR(mIfname),
type == AF_INET ? "0.0.0.0" : "::",
0, autoGateway.get());
RETURN_IF_FAILED(mNetUtils->do_ifc_remove_route(GET_CHAR(mIfname),
type == AF_INET ? "0.0.0.0" : "::",
0, autoGateway.get()));
}
return SUCCESS;
@ -1318,7 +1455,7 @@ int32_t NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
/**
* Add host route for given network interface.
*/
int32_t NetworkUtils::addHostRoute(NetworkParams& aOptions)
CommandResult NetworkUtils::addHostRoute(NetworkParams& aOptions)
{
NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
NS_ConvertUTF16toUTF8 autoHostname(aOptions.mIp);
@ -1342,7 +1479,7 @@ int32_t NetworkUtils::addHostRoute(NetworkParams& aOptions)
/**
* Remove host route for given network interface.
*/
int32_t NetworkUtils::removeHostRoute(NetworkParams& aOptions)
CommandResult NetworkUtils::removeHostRoute(NetworkParams& aOptions)
{
NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
NS_ConvertUTF16toUTF8 autoHostname(aOptions.mIp);
@ -1366,12 +1503,12 @@ int32_t NetworkUtils::removeHostRoute(NetworkParams& aOptions)
/**
* Remove the routes associated with the named interface.
*/
int32_t NetworkUtils::removeHostRoutes(NetworkParams& aOptions)
CommandResult NetworkUtils::removeHostRoutes(NetworkParams& aOptions)
{
return mNetUtils->do_ifc_remove_host_routes(GET_CHAR(mIfname));
}
int32_t NetworkUtils::removeNetworkRoute(NetworkParams& aOptions)
CommandResult NetworkUtils::removeNetworkRoute(NetworkParams& aOptions)
{
NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
NS_ConvertUTF16toUTF8 autoIp(aOptions.mIp);
@ -1406,10 +1543,10 @@ int32_t NetworkUtils::removeNetworkRoute(NetworkParams& aOptions)
}
// Remove default route.
mNetUtils->do_ifc_remove_route(autoIfname.get(), "::", 0, NULL);
RETURN_IF_FAILED(mNetUtils->do_ifc_remove_route(autoIfname.get(), "::", 0, NULL));
// Remove subnet route.
mNetUtils->do_ifc_remove_route(autoIfname.get(), subnetStr, prefixLength, NULL);
RETURN_IF_FAILED(mNetUtils->do_ifc_remove_route(autoIfname.get(), subnetStr, prefixLength, NULL));
return SUCCESS;
}
@ -1422,12 +1559,12 @@ int32_t NetworkUtils::removeNetworkRoute(NetworkParams& aOptions)
addr.s_addr = subnet;
const char* dst = inet_ntoa(addr);
mNetUtils->do_ifc_remove_default_route(autoIfname.get());
mNetUtils->do_ifc_remove_route(autoIfname.get(), dst, prefixLength, gateway);
RETURN_IF_FAILED(mNetUtils->do_ifc_remove_default_route(autoIfname.get()));
RETURN_IF_FAILED(mNetUtils->do_ifc_remove_route(autoIfname.get(), dst, prefixLength, gateway));
return SUCCESS;
}
int32_t NetworkUtils::addSecondaryRoute(NetworkParams& aOptions)
CommandResult NetworkUtils::addSecondaryRoute(NetworkParams& aOptions)
{
char command[MAX_COMMAND_SIZE];
snprintf(command, MAX_COMMAND_SIZE - 1,
@ -1441,7 +1578,7 @@ int32_t NetworkUtils::addSecondaryRoute(NetworkParams& aOptions)
return SUCCESS;
}
int32_t NetworkUtils::removeSecondaryRoute(NetworkParams& aOptions)
CommandResult NetworkUtils::removeSecondaryRoute(NetworkParams& aOptions)
{
char command[MAX_COMMAND_SIZE];
snprintf(command, MAX_COMMAND_SIZE - 1,
@ -1455,41 +1592,41 @@ int32_t NetworkUtils::removeSecondaryRoute(NetworkParams& aOptions)
return SUCCESS;
}
int32_t NetworkUtils::setNetworkInterfaceAlarm(NetworkParams& aOptions)
CommandResult NetworkUtils::setNetworkInterfaceAlarm(NetworkParams& aOptions)
{
DEBUG("setNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
RUN_CHAIN(aOptions, sNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
return SUCCESS;
return CommandResult::Pending();
}
int32_t NetworkUtils::enableNetworkInterfaceAlarm(NetworkParams& aOptions)
CommandResult NetworkUtils::enableNetworkInterfaceAlarm(NetworkParams& aOptions)
{
DEBUG("enableNetworkInterfaceAlarm: %s", GET_CHAR(mIfname));
RUN_CHAIN(aOptions, sNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
return SUCCESS;
return CommandResult::Pending();
}
int32_t NetworkUtils::disableNetworkInterfaceAlarm(NetworkParams& aOptions)
CommandResult NetworkUtils::disableNetworkInterfaceAlarm(NetworkParams& aOptions)
{
DEBUG("disableNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
RUN_CHAIN(aOptions, sNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
return SUCCESS;
return CommandResult::Pending();
}
/**
* handling main thread's reload Wifi firmware request
*/
int32_t NetworkUtils::setWifiOperationMode(NetworkParams& aOptions)
CommandResult NetworkUtils::setWifiOperationMode(NetworkParams& aOptions)
{
DEBUG("setWifiOperationMode: %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
RUN_CHAIN(aOptions, sWifiOperationModeChain, wifiOperationModeFail);
return SUCCESS;
return CommandResult::Pending();
}
/**
* handling main thread's enable/disable WiFi Tethering request
*/
int32_t NetworkUtils::setWifiTethering(NetworkParams& aOptions)
CommandResult NetworkUtils::setWifiTethering(NetworkParams& aOptions)
{
bool enable = aOptions.mEnable;
IFProperties interfaceProperties;
@ -1518,10 +1655,10 @@ int32_t NetworkUtils::setWifiTethering(NetworkParams& aOptions)
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
RUN_CHAIN(aOptions, sWifiDisableChain, wifiTetheringFail)
}
return SUCCESS;
return CommandResult::Pending();
}
int32_t NetworkUtils::setUSBTethering(NetworkParams& aOptions)
CommandResult NetworkUtils::setUSBTethering(NetworkParams& aOptions)
{
bool enable = aOptions.mEnable;
IFProperties interfaceProperties;
@ -1550,7 +1687,7 @@ int32_t NetworkUtils::setUSBTethering(NetworkParams& aOptions)
GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
RUN_CHAIN(aOptions, sUSBDisableChain, usbTetheringFail)
}
return SUCCESS;
return CommandResult::Pending();
}
void NetworkUtils::escapeQuote(nsCString& aString)
@ -1559,7 +1696,7 @@ void NetworkUtils::escapeQuote(nsCString& aString)
aString.ReplaceSubstring("\"", "\\\"");
}
void NetworkUtils::checkUsbRndisState(NetworkParams& aOptions)
CommandResult NetworkUtils::checkUsbRndisState(NetworkParams& aOptions)
{
static uint32_t retry = 0;
@ -1574,27 +1711,25 @@ void NetworkUtils::checkUsbRndisState(NetworkParams& aOptions)
NetworkResultOptions result;
result.mEnable = aOptions.mEnable;
result.mResult = true;
postMessage(aOptions, result);
retry = 0;
return;
return result;
}
if (retry < USB_FUNCTION_RETRY_TIMES) {
retry++;
usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
checkUsbRndisState(aOptions);
return;
return checkUsbRndisState(aOptions);
}
NetworkResultOptions result;
result.mResult = false;
postMessage(aOptions, result);
retry = 0;
return result;
}
/**
* Modify usb function's property to turn on USB RNDIS function
*/
int32_t NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
CommandResult NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
{
bool report = aOptions.mReport;
@ -1650,7 +1785,7 @@ int32_t NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
// Trigger the timer to check usb state and report the result to NetworkManager.
if (report) {
usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
checkUsbRndisState(aOptions);
return checkUsbRndisState(aOptions);
}
return SUCCESS;
}
@ -1658,10 +1793,10 @@ int32_t NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
/**
* handling upstream interface change event.
*/
int32_t NetworkUtils::updateUpStream(NetworkParams& aOptions)
CommandResult NetworkUtils::updateUpStream(NetworkParams& aOptions)
{
RUN_CHAIN(aOptions, sUpdateUpStreamChain, updateUpStreamFail)
return SUCCESS;
return CommandResult::Pending();
}
void NetworkUtils::sendBroadcastMessage(uint32_t code, char* reason)

View File

@ -28,48 +28,6 @@ public:
NetworkParams() {
}
NetworkParams(const NetworkParams& aOther) {
mIp = aOther.mIp;
mCmd = aOther.mCmd;
mDomain = aOther.mDomain;
mGateway = aOther.mGateway;
mGateways = aOther.mGateways;
mId = aOther.mId;
mIfname = aOther.mIfname;
mPrefixLength = aOther.mPrefixLength;
mOldIfname = aOther.mOldIfname;
mMode = aOther.mMode;
mReport = aOther.mReport;
mIsAsync = aOther.mIsAsync;
mEnabled = aOther.mEnabled;
mWifictrlinterfacename = aOther.mWifictrlinterfacename;
mInternalIfname = aOther.mInternalIfname;
mExternalIfname = aOther.mExternalIfname;
mEnable = aOther.mEnable;
mSsid = aOther.mSsid;
mSecurity = aOther.mSecurity;
mKey = aOther.mKey;
mPrefix = aOther.mPrefix;
mLink = aOther.mLink;
mInterfaceList = aOther.mInterfaceList;
mWifiStartIp = aOther.mWifiStartIp;
mWifiEndIp = aOther.mWifiEndIp;
mUsbStartIp = aOther.mUsbStartIp;
mUsbEndIp = aOther.mUsbEndIp;
mDns1 = aOther.mDns1;
mDns2 = aOther.mDns2;
mDnses = aOther.mDnses;
mStartIp = aOther.mStartIp;
mEndIp = aOther.mEndIp;
mServerIp = aOther.mServerIp;
mMaskLength = aOther.mMaskLength;
mPreInternalIfname = aOther.mPreInternalIfname;
mPreExternalIfname = aOther.mPreExternalIfname;
mCurInternalIfname = aOther.mCurInternalIfname;
mCurExternalIfname = aOther.mCurExternalIfname;
mThreshold = aOther.mThreshold;
}
NetworkParams(const mozilla::dom::NetworkCommandOptions& aOther) {
#define COPY_SEQUENCE_FIELD(prop, type) \
@ -112,7 +70,6 @@ public:
COPY_OPT_STRING_FIELD(mOldIfname, EmptyString())
COPY_OPT_STRING_FIELD(mMode, EmptyString())
COPY_OPT_FIELD(mReport, false)
COPY_OPT_FIELD(mIsAsync, false)
COPY_OPT_FIELD(mEnabled, false)
COPY_OPT_STRING_FIELD(mWifictrlinterfacename, EmptyString())
COPY_OPT_STRING_FIELD(mInternalIfname, EmptyString())
@ -140,6 +97,11 @@ public:
COPY_OPT_STRING_FIELD(mCurInternalIfname, EmptyString())
COPY_OPT_STRING_FIELD(mCurExternalIfname, EmptyString())
COPY_OPT_FIELD(mThreshold, -1)
COPY_OPT_FIELD(mIpaddr, 0)
COPY_OPT_FIELD(mMask, 0)
COPY_OPT_FIELD(mGateway_long, 0)
COPY_OPT_FIELD(mDns1_long, 0)
COPY_OPT_FIELD(mDns2_long, 0)
#undef COPY_SEQUENCE_FIELD
#undef COPY_OPT_STRING_FIELD
@ -158,7 +120,6 @@ public:
nsString mOldIfname;
nsString mMode;
bool mReport;
bool mIsAsync;
bool mEnabled;
nsString mWifictrlinterfacename;
nsString mInternalIfname;
@ -186,6 +147,11 @@ public:
nsString mCurInternalIfname;
nsString mCurExternalIfname;
long mThreshold;
long mIpaddr;
long mMask;
long mGateway_long;
long mDns1_long;
long mDns2_long;
};
// CommandChain store the necessary information to execute command one by one.
@ -235,6 +201,25 @@ private:
ErrorCallback mError;
};
// A helper class to easily construct a resolved
// or a pending result for command execution.
class CommandResult
{
public:
struct Pending {};
public:
CommandResult(int32_t aResultCode);
CommandResult(const mozilla::dom::NetworkResultOptions& aResult);
CommandResult(const Pending&);
bool isPending() const;
mozilla::dom::NetworkResultOptions mResult;
private:
bool mIsPending;
};
class NetworkUtils MOZ_FINAL
{
public:
@ -250,24 +235,29 @@ private:
/**
* Commands supported by NetworkUtils.
*/
int32_t setDNS(NetworkParams& aOptions);
int32_t setDefaultRouteAndDNS(NetworkParams& aOptions);
int32_t addHostRoute(NetworkParams& aOptions);
int32_t removeDefaultRoute(NetworkParams& aOptions);
int32_t removeHostRoute(NetworkParams& aOptions);
int32_t removeHostRoutes(NetworkParams& aOptions);
int32_t removeNetworkRoute(NetworkParams& aOptions);
int32_t addSecondaryRoute(NetworkParams& aOptions);
int32_t removeSecondaryRoute(NetworkParams& aOptions);
int32_t setNetworkInterfaceAlarm(NetworkParams& aOptions);
int32_t enableNetworkInterfaceAlarm(NetworkParams& aOptions);
int32_t disableNetworkInterfaceAlarm(NetworkParams& aOptions);
int32_t setWifiOperationMode(NetworkParams& aOptions);
int32_t setDhcpServer(NetworkParams& aOptions);
int32_t setWifiTethering(NetworkParams& aOptions);
int32_t setUSBTethering(NetworkParams& aOptions);
int32_t enableUsbRndis(NetworkParams& aOptions);
int32_t updateUpStream(NetworkParams& aOptions);
CommandResult configureInterface(NetworkParams& aOptions);
CommandResult dhcpRequest(NetworkParams& aOptions);
CommandResult enableInterface(NetworkParams& aOptions);
CommandResult disableInterface(NetworkParams& aOptions);
CommandResult resetConnections(NetworkParams& aOptions);
CommandResult setDefaultRoute(NetworkParams& aOptions);
CommandResult addHostRoute(NetworkParams& aOptions);
CommandResult removeDefaultRoute(NetworkParams& aOptions);
CommandResult removeHostRoute(NetworkParams& aOptions);
CommandResult removeHostRoutes(NetworkParams& aOptions);
CommandResult removeNetworkRoute(NetworkParams& aOptions);
CommandResult setDNS(NetworkParams& aOptions);
CommandResult addSecondaryRoute(NetworkParams& aOptions);
CommandResult removeSecondaryRoute(NetworkParams& aOptions);
CommandResult setNetworkInterfaceAlarm(NetworkParams& aOptions);
CommandResult enableNetworkInterfaceAlarm(NetworkParams& aOptions);
CommandResult disableNetworkInterfaceAlarm(NetworkParams& aOptions);
CommandResult setWifiOperationMode(NetworkParams& aOptions);
CommandResult setDhcpServer(NetworkParams& aOptions);
CommandResult setWifiTethering(NetworkParams& aOptions);
CommandResult setUSBTethering(NetworkParams& aOptions);
CommandResult enableUsbRndis(NetworkParams& aOptions);
CommandResult updateUpStream(NetworkParams& aOptions);
/**
* function pointer array holds all netd commands should be executed
@ -360,7 +350,7 @@ private:
/**
* Utility functions.
*/
void checkUsbRndisState(NetworkParams& aOptions);
CommandResult checkUsbRndisState(NetworkParams& aOptions);
void dumpParams(NetworkParams& aOptions, const char* aType);
static void escapeQuote(nsCString& aString);

View File

@ -33,24 +33,9 @@ class NetworkResultDispatcher : public nsRunnable
{
public:
NetworkResultDispatcher(const NetworkResultOptions& aResult)
: mResult(aResult)
{
MOZ_ASSERT(!NS_IsMainThread());
#define COPY_FIELD(prop) mResult.prop = aResult.prop;
COPY_FIELD(mId)
COPY_FIELD(mRet)
COPY_FIELD(mBroadcast)
COPY_FIELD(mTopic)
COPY_FIELD(mReason)
COPY_FIELD(mResultCode)
COPY_FIELD(mResultReason)
COPY_FIELD(mError)
COPY_FIELD(mEnable)
COPY_FIELD(mResult)
COPY_FIELD(mSuccess)
COPY_FIELD(mCurExternalIfname)
COPY_FIELD(mCurInternalIfname)
#undef COPY_FIELD
}
NS_IMETHOD Run()

View File

@ -101,10 +101,65 @@ interface nsIUpdateUpStreamCallback : nsISupports
void updateUpStreamResult(in boolean success, in DOMString externalIfname);
};
[scriptable, function, uuid(eedca6c0-1310-11e4-9191-0800200c9a66)]
interface nsISetDnsCallback : nsISupports
{
/**
* Callback function used to report the result of setting DNS server.
*
* @param error
* An error message if the operation wasn't successful,
* or `null` if it was.
*/
void setDnsResult(in jsval error);
};
[scriptable, function, uuid(5d0e1a60-1187-11e4-9191-0800200c9a66)]
interface nsINativeCommandCallback : nsISupports
{
/**
* Callback function used to report the result of a network native command.
*
* @param success
* Boolean to indicate the operation is successful or not.
*/
void nativeCommandResult(in boolean success);
};
[scriptable, function, uuid(694abb80-1187-11e4-9191-0800200c9a66)]
interface nsIDhcpRequestCallback : nsISupports
{
/**
* Callback function used to report the result of DHCP client request.
*
* @param success
* Boolean to indicate the operation is successful or not.
*
* @param dhcpInfo
* An object to represent the successful DHCP request:
*
* - gateway_str: string
* - dns1_str: string
* - dns2_str: string
* - mask_str: string
* - server_str: string
* - vendor_str: string
* - lease: long
* - mask: long
* - ipaddr: long
* - gateway: long
* - dns1: long
* - dns2: long
* - server: long
*/
void dhcpRequestResult(in boolean success, in jsval dhcpInfo);
};
/**
* Provide network services.
*/
[scriptable, uuid(ddb38428-0cf2-4c6a-a3c9-5e2f00fc54db)]
[scriptable, uuid(9f1d78e0-1314-11e4-9191-0800200c9a66)]
interface nsINetworkService : nsISupports
{
/**
@ -229,19 +284,26 @@ interface nsINetworkService : nsISupports
*
* @param networkInterface
* The network interface which contains the DNS we want to set.
*
* @param callback
* Callback to notify the result of setting DNS server.
*/
void setDNS(in nsINetworkInterface networkInterface);
void setDNS(in nsINetworkInterface networkInterface,
in nsISetDnsCallback callback);
/**
* Set default route and DNS.
* Set default route.
*
* @param networkInterface
* The network interface we want to set to the default route and dns.
* The network interface we want to set to the default route.
* @param oldInterface
* The previous network interface.
* @param callback
* Callback to notify the result of setting default route.
*/
void setDefaultRouteAndDNS(in nsINetworkInterface networkInterface,
in nsINetworkInterface oldInterface);
void setDefaultRoute(in nsINetworkInterface networkInterface,
in nsINetworkInterface oldInterface,
in nsINativeCommandCallback callback);
/**
* Remove default route.
@ -341,4 +403,71 @@ interface nsINetworkService : nsISupports
void updateUpStream(in jsval previous,
in jsval current,
in nsIUpdateUpStreamCallback callback);
/**
* Configure a network interface.
*
* @param config
* An object containing the detail that we want to configure the interface:
*
* - ifname: string
* - ipaddr: long
* - mask: long
* - gateway: long
* - dns1: long
* - dns2: long
*
* @param callback
* Callback to notify the result of configurating network interface.
*/
void configureInterface(in jsval config,
in nsINativeCommandCallback callback);
/**
* Issue a DHCP client request.
*
* @param networkInterface
* The network interface which we wnat to do the DHCP request on.
*
* @param callback
* Callback to notify the result of the DHCP request.
*/
void dhcpRequest(in DOMString interfaceName,
in nsIDhcpRequestCallback callback);
/**
* Enable a network interface.
*
* @param networkInterface
* The network interface name which we want to enable.
*
* @param callback
* Callback to notify the result of disabling network interface.
*/
void enableInterface(in DOMString interfaceName,
in nsINativeCommandCallback callback);
/**
* Disable a network interface.
*
* @param networkInterface
* The network interface name which we want to disable.
*
* @param callback
* Callback to notify the result of disabling network interface.
*/
void disableInterface(in DOMString interfaceName,
in nsINativeCommandCallback callback);
/**
* Reset all connections
*
* @param networkInterface
* The network interface name which we want to reset.
*
* @param callback
* Callback to notify the result of resetting connections.
*/
void resetConnections(in DOMString interfaceName,
in nsINativeCommandCallback callback);
};

View File

@ -6,6 +6,9 @@ interface FMRadio : EventTarget {
/* Indicates if the FM radio is enabled. */
readonly attribute boolean enabled;
/* Indicates if RDS reception is enabled */
readonly attribute boolean rdsEnabled;
/* Indicates if the antenna is plugged and available. */
readonly attribute boolean antennaAvailable;
@ -31,12 +34,58 @@ interface FMRadio : EventTarget {
*/
readonly attribute double channelWidth;
/**
* This is a mask consisting of bits corresponding to
* (1 << groupcode) that can be specified to receive
* raw RDS groups of specific group types. Note that
* groupcode corresponds to the upper 5 bits in block B.
*/
attribute unsigned long rdsGroupMask;
/**
* The Program Identification (PI) code.
* Available if RDS is enabled on both the station and on this device.
* The value is null otherwise.
*/
readonly attribute unsigned short? pi;
/**
* The Program Type (PTY) code.
* Available if RDS is enabled on both the station and on this device.
* The value is null otherwise.
*/
readonly attribute octet? pty;
/**
* The Program Service (PS) name.
* Available if RDS is enabled on the station and on this device
*/
readonly attribute DOMString? ps;
/**
* The radiotext, as provided by group 2A/2B.
* Available if RDS is enabled on the station and on this device
*/
readonly attribute DOMString? rt;
/**
* The last RDS group received.
* Available if RDS is enabled on the station and on this device
*/
readonly attribute Uint16Array? rdsgroup;
/* Fired when the FM radio is enabled. */
attribute EventHandler onenabled;
/* Fired when the FM radio is disabled. */
attribute EventHandler ondisabled;
/* Fired when the RDS is enabled. */
attribute EventHandler onrdsenabled;
/* Fired when the RDS is disabled. */
attribute EventHandler onrdsdisabled;
/**
* Fired when the antenna becomes available or unavailable, i.e., fired when
* the antennaAvailable attribute changes.
@ -46,6 +95,21 @@ interface FMRadio : EventTarget {
/* Fired when the FM radio's frequency is changed. */
attribute EventHandler onfrequencychange;
/* Fired when the PI code changes */
attribute EventHandler onpichange;
/* Fired when the PTY changes */
attribute EventHandler onptychange;
/* Fired when the PS name changes */
attribute EventHandler onpschange;
/* Fired when the radiotext changes */
attribute EventHandler onrtchange;
/* Fired when we get a new RDS group */
attribute EventHandler onnewrdsgroup;
/**
* Power the FM radio off. The disabled event will be fired if this request
* completes successfully.
@ -94,5 +158,19 @@ interface FMRadio : EventTarget {
* error will be fired.
*/
DOMRequest cancelSeek();
/**
* Enable RDS reception.
*
* If the radio is off, RDS will be enabled when the radio is turned on.
*/
DOMRequest enableRDS();
/**
* Disable RDS reception.
*
* If the radio is off, RDS will not be enabled when the radio is turned on.
*/
DOMRequest disableRDS();
};

View File

@ -22,7 +22,6 @@ dictionary NetworkCommandOptions
sequence<DOMString> gateways; // for "setDefaultRouteAndDNS", "removeDefaultRoute".
DOMString mode; // for "setWifiOperationMode".
boolean report; // for "setWifiOperationMode".
boolean isAsync; // for "setWifiOperationMode".
boolean enabled; // for "setDhcpServer".
DOMString wifictrlinterfacename; // for "setWifiTethering".
DOMString internalIfname; // for "setWifiTethering".
@ -50,6 +49,12 @@ dictionary NetworkCommandOptions
DOMString preExternalIfname; // for "updateUpStream".
DOMString curInternalIfname; // for "updateUpStream".
DOMString curExternalIfname; // for "updateUpStream".
long ipaddr; // for "ifc_configure".
long mask; // for "ifc_configure".
long gateway_long; // for "ifc_configure".
long dns1_long; // for "ifc_configure".
long dns2_long; // for "ifc_configure".
};
/**
@ -73,4 +78,22 @@ dictionary NetworkResultOptions
boolean success = false; // for "setDhcpServer".
DOMString curExternalIfname = ""; // for "updateUpStream".
DOMString curInternalIfname = ""; // for "updateUpStream".
DOMString reply = ""; // for "command".
DOMString route = ""; // for "ifc_get_default_route".
DOMString ipaddr_str = ""; // The following are for the result of
// dhcp_do_request.
DOMString gateway_str = "";
DOMString dns1_str = "";
DOMString dns2_str = "";
DOMString mask_str = "";
DOMString server_str = "";
DOMString vendor_str = "";
long lease = 0;
long mask = 0;
long ipaddr = 0;
long gateway = 0;
long dns1 = 0;
long dns2 = 0;
long server = 0;
};

View File

@ -10,22 +10,6 @@ dictionary WifiCommandOptions
long id = 0; // opaque id.
DOMString cmd = ""; // the command name.
DOMString request; // for "command"
DOMString ifname; // for "ifc_reset_connections", "ifc_enable",
// "ifc_disable", "ifc_remove_host_routes",
// "ifc_remove_default_route", "dhcp_stop",
// "dhcp_release_lease", "ifc_get_default_route",
// "ifc_add_host_route", "ifc_set_default_route",
// "ifc_configure", "dhcp_do_request",
// "dhcp_do_request_renew".
long route; // for "ifc_add_host_route", "ifc_set_default_route".
long ipaddr; // for "ifc_configure".
long mask; // for "ifc_configure".
long gateway; // for "ifc_configure".
long dns1; // for "ifc_configure".
long dns2; // for "ifc_configure".
DOMString key; // for "property_get", "property_set".
DOMString value; // for "property_set".
DOMString defaultValue; // for "property_get".
};
/**
@ -37,24 +21,6 @@ dictionary WifiResultOptions
long status = 0; // the return status of the command.
// Used by most commands.
DOMString reply = ""; // for "command".
DOMString route = ""; // for "ifc_get_default_route".
DOMString error = ""; // for "dhcp_get_errmsg".
DOMString value = ""; // for "property_get".
DOMString ipaddr_str = ""; // The following are for the result of
// dhcp_do_request.
DOMString gateway_str = "";
DOMString dns1_str = "";
DOMString dns2_str = "";
DOMString mask_str = "";
DOMString server_str = "";
DOMString vendor_str = "";
long lease = 0;
long mask = 0;
long ipaddr = 0;
long gateway = 0;
long dns1 = 0;
long dns2 = 0;
long server = 0;
};

View File

@ -30,23 +30,8 @@ this.WifiNetUtil = function(controlMessage) {
var util = {};
util.configureInterface = function(cfg, callback) {
let message = { cmd: "ifc_configure",
ifname: cfg.ifname,
ipaddr: cfg.ipaddr,
mask: cfg.mask,
gateway: cfg.gateway,
dns1: cfg.dns1,
dns2: cfg.dns2 };
controlMessage(message, function(data) {
callback(!data.status);
});
};
util.runDhcp = function (ifname, callback) {
controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
var dhcpInfo = data.status ? null : data;
gNetworkService.dhcpRequest(ifname, function(success, dhcpInfo) {
util.runIpConfig(ifname, dhcpInfo, callback);
});
};
@ -62,18 +47,6 @@ this.WifiNetUtil = function(controlMessage) {
stopProcess(dhcpService, processName, callback);
};
util.enableInterface = function (ifname, callback) {
controlMessage({ cmd: "ifc_enable", ifname: ifname }, function (data) {
callback(!data.status);
});
};
util.disableInterface = function (ifname, callback) {
controlMessage({ cmd: "ifc_disable", ifname: ifname }, function (data) {
callback(!data.status);
});
};
util.startDhcpServer = function (config, callback) {
gNetworkService.setDhcpServer(true, config, function (error) {
callback(!error);
@ -86,60 +59,6 @@ this.WifiNetUtil = function(controlMessage) {
});
};
util.addHostRoute = function (ifname, route, callback) {
controlMessage({ cmd: "ifc_add_host_route", ifname: ifname, route: route }, function(data) {
callback(!data.status);
});
};
util.removeHostRoutes = function (ifname, callback) {
controlMessage({ cmd: "ifc_remove_host_routes", ifname: ifname }, function(data) {
callback(!data.status);
});
};
util.setDefaultRoute = function (ifname, route, callback) {
controlMessage({ cmd: "ifc_set_default_route", ifname: ifname, route: route }, function(data) {
callback(!data.status);
});
};
util.getDefaultRoute = function (ifname, callback) {
controlMessage({ cmd: "ifc_get_default_route", ifname: ifname }, function(data) {
callback(!data.route);
});
};
util.removeDefaultRoute = function (ifname, callback) {
controlMessage({ cmd: "ifc_remove_default_route", ifname: ifname }, function(data) {
callback(!data.status);
});
};
util.resetConnections = function (ifname, callback) {
controlMessage({ cmd: "ifc_reset_connections", ifname: ifname }, function(data) {
callback(!data.status);
});
};
util.releaseDhcpLease = function (ifname, callback) {
controlMessage({ cmd: "dhcp_release_lease", ifname: ifname }, function(data) {
callback(!data.status);
});
};
util.getDhcpError = function (callback) {
controlMessage({ cmd: "dhcp_get_errmsg" }, function(data) {
callback(data.error);
});
};
util.runDhcpRenew = function (ifname, callback) {
controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
callback(data.status ? null : data);
});
};
util.runIpConfig = function (name, data, callback) {
if (!data) {
debug("IP config failed to run");

View File

@ -21,6 +21,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
"@mozilla.org/network/manager;1",
"nsINetworkManager");
XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
"@mozilla.org/network/service;1",
"nsINetworkService");
this.EXPORTED_SYMBOLS = ["WifiP2pManager"];
const EVENT_IGNORED = -1;
@ -647,7 +651,7 @@ function P2pStateMachine(aP2pCommand, aNetUtil) {
// Step 4: Enable p2p0 net interface. wpa_supplicant may have
// already done it for us.
aNetUtil.enableInterface(P2P_INTERFACE_NAME, function (success) {
gNetworkService.enableInterface(P2P_INTERFACE_NAME, function (success) {
onSuccess();
});
});
@ -1318,7 +1322,7 @@ function P2pStateMachine(aP2pCommand, aNetUtil) {
debug('P2P function disabled');
aP2pCommand.closeSupplicantConnection(function (status) {
debug('Supplicant connection closed');
aNetUtil.disableInterface(P2P_INTERFACE_NAME, function (success){
gNetworkService.disableInterface(P2P_INTERFACE_NAME, function (success){
debug('Disabled interface: ' + P2P_INTERFACE_NAME);
_onDisabled(true);
_sm.gotoState(stateDisabled);

View File

@ -89,36 +89,10 @@ class WifiResultDispatcher : public nsRunnable
{
public:
WifiResultDispatcher(WifiResultOptions& aResult, const nsACString& aInterface)
: mInterface(aInterface)
: mResult(aResult)
, mInterface(aInterface)
{
MOZ_ASSERT(!NS_IsMainThread());
// XXX: is there a better way to copy webidl dictionnaries?
// the copy constructor is private.
#define COPY_FIELD(prop) mResult.prop = aResult.prop;
COPY_FIELD(mId)
COPY_FIELD(mStatus)
COPY_FIELD(mReply)
COPY_FIELD(mRoute)
COPY_FIELD(mError)
COPY_FIELD(mValue)
COPY_FIELD(mIpaddr_str)
COPY_FIELD(mGateway_str)
COPY_FIELD(mDns1_str)
COPY_FIELD(mDns2_str)
COPY_FIELD(mMask_str)
COPY_FIELD(mServer_str)
COPY_FIELD(mVendor_str)
COPY_FIELD(mLease)
COPY_FIELD(mMask)
COPY_FIELD(mIpaddr)
COPY_FIELD(mGateway)
COPY_FIELD(mDns1)
COPY_FIELD(mDns2)
COPY_FIELD(mServer)
#undef COPY_FIELD
}
NS_IMETHOD Run()

View File

@ -8,7 +8,6 @@
#include <cutils/properties.h>
#include "prinit.h"
#include "js/CharacterEncoding.h"
#include "mozilla/dom/network/NetUtils.h"
using namespace mozilla::dom;
@ -380,14 +379,17 @@ public:
// Concrete class to use to access the wpa supplicant.
WpaSupplicant::WpaSupplicant()
{
if (NetUtils::SdkVersion() < 16) {
char propVersion[PROPERTY_VALUE_MAX];
property_get("ro.build.version.sdk", propVersion, "0");
mSdkVersion = strtol(propVersion, nullptr, 10);
if (mSdkVersion < 16) {
mImpl = new ICSWpaSupplicantImpl();
} else if (NetUtils::SdkVersion() < 19) {
} else if (mSdkVersion < 19) {
mImpl = new JBWpaSupplicantImpl();
} else {
mImpl = new KKWpaSupplicantImpl();
}
mNetUtils = new NetUtils();
mWifiHotspotUtils = new WifiHotspotUtils();
};
@ -418,9 +420,6 @@ bool WpaSupplicant::ExecuteCommand(CommandOptions aOptions,
const nsCString& aInterface)
{
CHECK_HWLIB(false)
if (!mNetUtils->GetSharedLibrary()) {
return false;
}
if (!mWifiHotspotUtils->GetSharedLibrary()) {
return false;
@ -455,81 +454,6 @@ bool WpaSupplicant::ExecuteCommand(CommandOptions aOptions,
aResult.mStatus = mImpl->do_wifi_stop_supplicant(0);
} else if (aOptions.mCmd.EqualsLiteral("connect_to_supplicant")) {
aResult.mStatus = mImpl->do_wifi_connect_to_supplicant(aInterface.get());
} else if (aOptions.mCmd.EqualsLiteral("ifc_enable")) {
aResult.mStatus = mNetUtils->do_ifc_enable(GET_CHAR(mIfname));
} else if (aOptions.mCmd.EqualsLiteral("ifc_disable")) {
aResult.mStatus = mNetUtils->do_ifc_disable(GET_CHAR(mIfname));
} else if (aOptions.mCmd.EqualsLiteral("ifc_configure")) {
aResult.mStatus = mNetUtils->do_ifc_configure(
GET_CHAR(mIfname), aOptions.mIpaddr, aOptions.mMask,
aOptions.mGateway, aOptions.mDns1, aOptions.mDns2
);
} else if (aOptions.mCmd.EqualsLiteral("ifc_reset_connections")) {
aResult.mStatus = mNetUtils->do_ifc_reset_connections(
GET_CHAR(mIfname), RESET_ALL_ADDRESSES
);
} else if (aOptions.mCmd.EqualsLiteral("dhcp_stop")) {
aResult.mStatus = mNetUtils->do_dhcp_stop(GET_CHAR(mIfname));
} else if (aOptions.mCmd.EqualsLiteral("dhcp_do_request")) {
char ipaddr[PROPERTY_VALUE_MAX];
char gateway[PROPERTY_VALUE_MAX];
uint32_t prefixLength;
char dns1[PROPERTY_VALUE_MAX];
char dns2[PROPERTY_VALUE_MAX];
char server[PROPERTY_VALUE_MAX];
uint32_t lease;
char vendorinfo[PROPERTY_VALUE_MAX];
aResult.mStatus =
mNetUtils->do_dhcp_do_request(GET_CHAR(mIfname),
ipaddr,
gateway,
&prefixLength,
dns1,
dns2,
server,
&lease,
vendorinfo);
if (aResult.mStatus == -1) {
// Early return since we failed.
return true;
}
aResult.mIpaddr_str = NS_ConvertUTF8toUTF16(ipaddr);
aResult.mGateway_str = NS_ConvertUTF8toUTF16(gateway);
aResult.mDns1_str = NS_ConvertUTF8toUTF16(dns1);
aResult.mDns2_str = NS_ConvertUTF8toUTF16(dns2);
aResult.mServer_str = NS_ConvertUTF8toUTF16(server);
aResult.mVendor_str = NS_ConvertUTF8toUTF16(vendorinfo);
aResult.mLease = lease;
aResult.mMask = MakeMask(prefixLength);
uint32_t inet4; // only support IPv4 for now.
#define INET_PTON(var, field) \
PR_BEGIN_MACRO \
inet_pton(AF_INET, var, &inet4); \
aResult.field = inet4; \
PR_END_MACRO
INET_PTON(ipaddr, mIpaddr);
INET_PTON(gateway, mGateway);
if (dns1[0] != '\0') {
INET_PTON(dns1, mDns1);
}
if (dns2[0] != '\0') {
INET_PTON(dns2, mDns2);
}
INET_PTON(server, mServer);
//aResult.mask_str = netHelpers.ipToString(obj.mask);
char inet_str[64];
if (inet_ntop(AF_INET, &aResult.mMask, inet_str, sizeof(inet_str))) {
aResult.mMask_str = NS_ConvertUTF8toUTF16(inet_str);
}
} else if (aOptions.mCmd.EqualsLiteral("hostapd_command")) {
size_t len = BUFFER_SIZE - 1;
char buffer[BUFFER_SIZE];
@ -595,7 +519,7 @@ WpaSupplicant::CheckBuffer(char* buffer, int32_t length,
return;
}
if (NetUtils::SdkVersion() < 18) {
if (mSdkVersion < 18) {
buffer[length] = 0;
LossyConvertUTF8toUTF16(buffer, length, aEvent);
return;

View File

@ -13,29 +13,12 @@
#include "nsString.h"
#include "nsAutoPtr.h"
#include "mozilla/dom/WifiOptionsBinding.h"
#include "mozilla/dom/network/NetUtils.h"
#include "WifiHotspotUtils.h"
// Needed to add a copy constructor to WifiCommandOptions.
struct CommandOptions
{
public:
CommandOptions(const CommandOptions& aOther) {
mId = aOther.mId;
mCmd = aOther.mCmd;
mRequest = aOther.mRequest;
mIfname = aOther.mIfname;
mRoute = aOther.mRoute;
mIpaddr = aOther.mIpaddr;
mMask = aOther.mMask;
mGateway = aOther.mGateway;
mDns1 = aOther.mDns1;
mDns2 = aOther.mDns2;
mKey = aOther.mKey;
mValue = aOther.mValue;
mDefaultValue = aOther.mDefaultValue;
}
CommandOptions(const mozilla::dom::WifiCommandOptions& aOther) {
#define COPY_OPT_FIELD(prop, defaultValue) \
@ -49,16 +32,6 @@ public:
COPY_FIELD(mId)
COPY_FIELD(mCmd)
COPY_OPT_FIELD(mRequest, EmptyString())
COPY_OPT_FIELD(mIfname, EmptyString())
COPY_OPT_FIELD(mIpaddr, 0)
COPY_OPT_FIELD(mRoute, 0)
COPY_OPT_FIELD(mMask, 0)
COPY_OPT_FIELD(mGateway, 0)
COPY_OPT_FIELD(mDns1, 0)
COPY_OPT_FIELD(mDns2, 0)
COPY_OPT_FIELD(mKey, EmptyString())
COPY_OPT_FIELD(mValue, EmptyString())
COPY_OPT_FIELD(mDefaultValue, EmptyString())
#undef COPY_OPT_FIELD
#undef COPY_FIELD
@ -66,18 +39,8 @@ public:
// All the fields, not Optional<> anymore to get copy constructors.
nsString mCmd;
nsString mDefaultValue;
int32_t mDns1;
int32_t mDns2;
int32_t mGateway;
int32_t mId;
nsString mIfname;
int32_t mIpaddr;
nsString mKey;
int32_t mMask;
nsString mRequest;
int32_t mRoute;
nsString mValue;
};
// Abstract class that exposes libhardware_legacy functions we need for
@ -130,9 +93,10 @@ public:
private:
nsAutoPtr<WpaSupplicantImpl> mImpl;
nsAutoPtr<NetUtils> mNetUtils;
nsAutoPtr<WifiHotspotUtils> mWifiHotspotUtils;
uint32_t mSdkVersion;
protected:
void CheckBuffer(char* buffer, int32_t length, nsAString& aEvent);
uint32_t MakeMask(uint32_t len);

View File

@ -415,8 +415,8 @@ var WifiManager = (function() {
// and routing table is changed but still cannot connect to network
// so the workaround here is disable interface the enable again to
// trigger network reconnect with static ip.
netUtil.disableInterface(manager.ifname, function (ok) {
netUtil.enableInterface(manager.ifname, function (ok) {
gNetworkService.disableInterface(manager.ifname, function (ok) {
gNetworkService.enableInterface(manager.ifname, function (ok) {
});
});
}
@ -442,12 +442,12 @@ var WifiManager = (function() {
}
// Set ip, mask length, gateway, dns to network interface
netUtil.configureInterface( { ifname: ifname,
ipaddr: staticIpInfo.ipaddr,
mask: staticIpInfo.maskLength,
gateway: staticIpInfo.gateway,
dns1: staticIpInfo.dns1,
dns2: staticIpInfo.dns2 }, function (data) {
gNetworkService.configureInterface( { ifname: ifname,
ipaddr: staticIpInfo.ipaddr,
mask: staticIpInfo.maskLength,
gateway: staticIpInfo.gateway,
dns1: staticIpInfo.dns1,
dns2: staticIpInfo.dns2 }, function (data) {
netUtil.runIpConfig(ifname, staticIpInfo, function(data) {
dhcpInfo = data.info;
notify("networkconnected", data);
@ -587,17 +587,17 @@ var WifiManager = (function() {
manager.connectionDropped = function(callback) {
// Reset network interface when connection drop
netUtil.configureInterface( { ifname: manager.ifname,
ipaddr: 0,
mask: 0,
gateway: 0,
dns1: 0,
dns2: 0 }, function (data) {
gNetworkService.configureInterface( { ifname: manager.ifname,
ipaddr: 0,
mask: 0,
gateway: 0,
dns1: 0,
dns2: 0 }, function (data) {
});
// If we got disconnected, kill the DHCP client in preparation for
// reconnection.
netUtil.resetConnections(manager.ifname, function() {
gNetworkService.resetConnections(manager.ifname, function() {
netUtil.stopDhcp(manager.ifname, function() {
callback();
});
@ -889,7 +889,7 @@ var WifiManager = (function() {
}
suppressEvents = true;
wifiCommand.killSupplicant(function() {
netUtil.disableInterface(manager.ifname, function (ok) {
gNetworkService.disableInterface(manager.ifname, function (ok) {
suppressEvents = false;
callback();
});
@ -996,7 +996,7 @@ var WifiManager = (function() {
}
manager.supplicantStarted = true;
netUtil.enableInterface(manager.ifname, function (ok) {
gNetworkService.enableInterface(manager.ifname, function (ok) {
callback(ok ? 0 : -1);
});
});
@ -1040,7 +1040,7 @@ var WifiManager = (function() {
wifiCommand.closeSupplicantConnection(function() {
manager.connectToSupplicant = false;
manager.state = "UNINITIALIZED";
netUtil.disableInterface(manager.ifname, function (ok) {
gNetworkService.disableInterface(manager.ifname, function (ok) {
unloadDriver(WIFI_FIRMWARE_STATION, callback);
});
});

View File

@ -1004,12 +1004,15 @@ ProcessPriorityToString(ProcessPriority aPriority,
}
static StaticAutoPtr<ObserverList<FMRadioOperationInformation> > sFMRadioObservers;
static StaticAutoPtr<ObserverList<FMRadioRDSGroup> > sFMRadioRDSObservers;
static void
InitializeFMRadioObserver()
{
if (!sFMRadioObservers) {
sFMRadioObservers = new ObserverList<FMRadioOperationInformation>;
sFMRadioRDSObservers = new ObserverList<FMRadioRDSGroup>;
ClearOnShutdown(&sFMRadioRDSObservers);
ClearOnShutdown(&sFMRadioObservers);
}
}
@ -1034,6 +1037,27 @@ NotifyFMRadioStatus(const FMRadioOperationInformation& aFMRadioState) {
sFMRadioObservers->Broadcast(aFMRadioState);
}
void
RegisterFMRadioRDSObserver(FMRadioRDSObserver* aFMRadioRDSObserver) {
AssertMainThread();
InitializeFMRadioObserver();
sFMRadioRDSObservers->AddObserver(aFMRadioRDSObserver);
}
void
UnregisterFMRadioRDSObserver(FMRadioRDSObserver* aFMRadioRDSObserver) {
AssertMainThread();
InitializeFMRadioObserver();
sFMRadioRDSObservers->RemoveObserver(aFMRadioRDSObserver);
}
void
NotifyFMRadioRDSGroup(const FMRadioRDSGroup& aRDSGroup) {
InitializeFMRadioObserver();
sFMRadioRDSObservers->Broadcast(aRDSGroup);
}
void
EnableFMRadio(const FMRadioSettings& aInfo) {
AssertMainThread();
@ -1088,6 +1112,18 @@ CancelFMRadioSeek() {
PROXY_IF_SANDBOXED(CancelFMRadioSeek());
}
void
EnableRDS(uint32_t aMask) {
AssertMainThread();
PROXY_IF_SANDBOXED(EnableRDS(aMask));
}
void
DisableRDS() {
AssertMainThread();
PROXY_IF_SANDBOXED(DisableRDS());
}
FMRadioSettings
GetFMBandSettings(FMRadioCountry aCountry) {
FMRadioSettings settings;

View File

@ -503,12 +503,28 @@ void RegisterFMRadioObserver(hal::FMRadioObserver* aRadioObserver);
*/
void UnregisterFMRadioObserver(hal::FMRadioObserver* aRadioObserver);
/**
* Register an observer for the FM radio.
*/
void RegisterFMRadioRDSObserver(hal::FMRadioRDSObserver* aRDSObserver);
/**
* Unregister the observer for the FM radio.
*/
void UnregisterFMRadioRDSObserver(hal::FMRadioRDSObserver* aRDSObserver);
/**
* Notify observers that a call to EnableFMRadio, DisableFMRadio, or FMRadioSeek
* has completed, and indicate what the call returned.
*/
void NotifyFMRadioStatus(const hal::FMRadioOperationInformation& aRadioState);
/**
* Notify observers of new RDS data
* This can be called on any thread.
*/
void NotifyFMRadioRDSGroup(const hal::FMRadioRDSGroup& aRDSGroup);
/**
* Enable the FM radio and configure it according to the settings in aInfo.
*/
@ -565,6 +581,16 @@ void CancelFMRadioSeek();
*/
hal::FMRadioSettings GetFMBandSettings(hal::FMRadioCountry aCountry);
/**
* Enable RDS data reception
*/
void EnableRDS(uint32_t aMask);
/**
* Disable RDS data reception
*/
void DisableRDS();
/**
* Start a watchdog to compulsively shutdown the system if it hangs.
* @param aMode Specify how to shutdown the system.

View File

@ -225,7 +225,9 @@ enum FMRadioCountry {
NUM_FM_RADIO_COUNTRY
};
class FMRadioRDSGroup;
typedef Observer<FMRadioOperationInformation> FMRadioObserver;
typedef Observer<FMRadioRDSGroup> FMRadioRDSObserver;
} // namespace hal
} // namespace mozilla

View File

@ -57,5 +57,13 @@ void
CancelFMRadioSeek()
{}
void
EnableRDS(uint32_t aMask)
{}
void
DisableRDS()
{}
} // hal_impl
} // namespace mozilla

View File

@ -25,6 +25,7 @@
#include <linux/videodev2.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <sys/types.h>
@ -42,6 +43,23 @@
#define V4L2_CID_RDS_RECEPTION (V4L2_CID_FM_RX_CLASS_BASE + 2)
#endif
#ifndef V4L2_RDS_BLOCK_MSK
struct v4l2_rds_data {
uint8_t lsb;
uint8_t msb;
uint8_t block;
} __attribute__ ((packed));
#define V4L2_RDS_BLOCK_MSK 0x7
#define V4L2_RDS_BLOCK_A 0
#define V4L2_RDS_BLOCK_B 1
#define V4L2_RDS_BLOCK_C 2
#define V4L2_RDS_BLOCK_D 3
#define V4L2_RDS_BLOCK_C_ALT 4
#define V4L2_RDS_BLOCK_INVALID 7
#define V4L2_RDS_BLOCK_CORRECTED 0x40
#define V4L2_RDS_BLOCK_ERROR 0x80
#endif
namespace mozilla {
namespace hal_impl {
@ -49,10 +67,13 @@ uint32_t GetFMRadioFrequency();
static int sRadioFD;
static bool sRadioEnabled;
static bool sRDSEnabled;
static pthread_t sRadioThread;
static pthread_t sRDSThread;
static hal::FMRadioSettings sRadioSettings;
static int sMsmFMVersion;
static bool sMsmFMMode;
static bool sRDSSupported;
static int
setControl(uint32_t id, int32_t value)
@ -311,6 +332,8 @@ EnableFMRadio(const hal::FMRadioSettings& aInfo)
hal::NotifyFMRadioStatus(info);
return;
}
sRDSSupported = cap.capabilities & V4L2_CAP_RDS_CAPTURE;
sRadioSettings = aInfo;
if (sMsmFMMode) {
@ -366,6 +389,9 @@ DisableFMRadio()
if (!sRadioEnabled)
return;
if (sRDSEnabled)
hal::DisableRDS();
sRadioEnabled = false;
if (sMsmFMMode) {
@ -494,5 +520,186 @@ void
CancelFMRadioSeek()
{}
/* Runs on the rds thread */
static void*
readRDSDataThread(void* data)
{
v4l2_rds_data rdsblocks[16];
uint16_t blocks[4];
ScopedClose pipefd((int)data);
ScopedClose epollfd(epoll_create(2));
if (epollfd < 0) {
HAL_LOG("Could not create epoll FD for RDS thread (%d)", errno);
return nullptr;
}
epoll_event event = {
EPOLLIN,
{ 0 }
};
event.data.fd = pipefd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pipefd, &event) < 0) {
HAL_LOG("Could not set up epoll FD for RDS thread (%d)", errno);
return nullptr;
}
event.data.fd = sRadioFD;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sRadioFD, &event) < 0) {
HAL_LOG("Could not set up epoll FD for RDS thread (%d)", errno);
return nullptr;
}
epoll_event events[2] = {{ 0 }};
int event_count;
uint32_t block_bitmap = 0;
while ((event_count = epoll_wait(epollfd, events, 2, -1)) > 0 ||
errno == EINTR) {
bool RDSDataAvailable = false;
for (int i = 0; i < event_count; i++) {
if (events[i].data.fd == pipefd) {
if (!sRDSEnabled)
return nullptr;
char tmp[32];
TEMP_FAILURE_RETRY(read(pipefd, tmp, sizeof(tmp)));
} else if (events[i].data.fd == sRadioFD) {
RDSDataAvailable = true;
}
}
if (!RDSDataAvailable)
continue;
ssize_t len =
TEMP_FAILURE_RETRY(read(sRadioFD, rdsblocks, sizeof(rdsblocks)));
if (len < 0) {
HAL_LOG("Unexpected error while reading RDS data %d", errno);
return nullptr;
}
int blockcount = len / sizeof(rdsblocks[0]);
int lastblock = -1;
for (int i = 0; i < blockcount; i++) {
if ((rdsblocks[i].block & V4L2_RDS_BLOCK_MSK) == V4L2_RDS_BLOCK_INVALID ||
rdsblocks[i].block & V4L2_RDS_BLOCK_ERROR) {
block_bitmap |= 1 << V4L2_RDS_BLOCK_INVALID;
continue;
}
int blocknum = rdsblocks[i].block & V4L2_RDS_BLOCK_MSK;
// In some cases, the full set of bits in an RDS group isn't
// needed, in which case version B RDS groups can be sent.
// Version B groups replace block C with block C' (V4L2_RDS_BLOCK_C_ALT).
// Block C' always stores the PI code, so receivers can find the PI
// code more quickly/reliably.
// However, we only process whole RDS groups, so it doesn't matter here.
if (blocknum == V4L2_RDS_BLOCK_C_ALT)
blocknum = V4L2_RDS_BLOCK_C;
if (blocknum > V4L2_RDS_BLOCK_D) {
HAL_LOG("Unexpected RDS block number %d. This is a driver bug.",
blocknum);
continue;
}
if (blocknum == V4L2_RDS_BLOCK_A)
block_bitmap = 0;
// Skip the group if we skipped a block.
// This stops us from processing blocks sent out of order.
if (block_bitmap != ((1 << blocknum) - 1)) {
block_bitmap |= 1 << V4L2_RDS_BLOCK_INVALID;
continue;
}
block_bitmap |= 1 << blocknum;
lastblock = blocknum;
blocks[blocknum] = (rdsblocks[i].msb << 8) | rdsblocks[i].lsb;
// Make sure we have all 4 blocks and that they're valid
if (block_bitmap != 0x0F)
continue;
hal::FMRadioRDSGroup group;
group.blockA() = blocks[V4L2_RDS_BLOCK_A];
group.blockB() = blocks[V4L2_RDS_BLOCK_B];
group.blockC() = blocks[V4L2_RDS_BLOCK_C];
group.blockD() = blocks[V4L2_RDS_BLOCK_D];
NotifyFMRadioRDSGroup(group);
}
}
return nullptr;
}
static int sRDSPipeFD;
void
EnableRDS(uint32_t aMask)
{
if (!sRadioEnabled || !sRDSSupported)
return;
if (sMsmFMMode)
setControl(V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_MASK, aMask);
if (sRDSEnabled)
return;
int pipefd[2];
int rc = pipe2(pipefd, O_NONBLOCK);
if (rc < 0) {
HAL_LOG("Could not create RDS thread signaling pipes (%d)", rc);
return;
}
ScopedClose writefd(pipefd[1]);
ScopedClose readfd(pipefd[0]);
rc = setControl(V4L2_CID_RDS_RECEPTION, true);
if (rc < 0) {
HAL_LOG("Could not enable RDS reception (%d)", rc);
return;
}
sRDSPipeFD = writefd;
sRDSEnabled = true;
rc = pthread_create(&sRDSThread, nullptr,
readRDSDataThread, (void*)pipefd[0]);
if (rc) {
HAL_LOG("Could not start RDS reception thread (%d)", rc);
setControl(V4L2_CID_RDS_RECEPTION, false);
sRDSEnabled = false;
return;
}
readfd.forget();
writefd.forget();
}
void
DisableRDS()
{
if (!sRadioEnabled || !sRDSEnabled)
return;
int rc = setControl(V4L2_CID_RDS_RECEPTION, false);
if (rc < 0) {
HAL_LOG("Could not disable RDS reception (%d)", rc);
}
sRDSEnabled = false;
write(sRDSPipeFD, "x", 1);
pthread_join(sRDSThread, nullptr);
close(sRDSPipeFD);
}
} // hal_impl
} // namespace mozilla

View File

@ -69,6 +69,13 @@ struct FMRadioOperationInformation {
uint32_t frequency;
};
struct FMRadioRDSGroup {
uint16_t blockA;
uint16_t blockB;
uint16_t blockC;
uint16_t blockD;
};
struct FMRadioSettings {
FMRadioCountry country;
uint32_t upperLimit;

View File

@ -426,6 +426,18 @@ CancelFMRadioSeek()
NS_RUNTIMEABORT("FM radio cannot be called from sandboxed contexts.");
}
void
EnableRDS(uint32_t aMask)
{
NS_RUNTIMEABORT("FM radio cannot be called from sandboxed contexts.");
}
void
DisableRDS()
{
NS_RUNTIMEABORT("FM radio cannot be called from sandboxed contexts.");
}
void
FactoryReset(FactoryResetReason& aReason)
{