Merge b2ginbound to m-c a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2015-05-07 15:23:42 -07:00
commit a92c521d88
17 changed files with 536 additions and 212 deletions

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -134,7 +134,7 @@
<project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
<project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
<project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
<project name="kernel/common" path="kernel" revision="a2977758950865feb5980996d8e889677dea3bd4"/>
<project name="kernel/common" path="kernel" revision="8696b132455224412a6725022acf672be80a0641"/>
<project name="platform/system/core" path="system/core" revision="7992618bd4ee33ce96897675a5c0a9b619122f13"/>
<project name="u-boot" path="u-boot" revision="f1502910977ac88f43da7bf9277c3523ad4b0b2f"/>
<project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="7d6e1269be7186b2073fa568958b357826692c4b"/>

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="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "83b27f522642ea573c57e882657ab5c73d4b07f4",
"git_revision": "bc5bfa18f795919b56b952bbf3637c235d0e13dc",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "6f889f462ec6387626570bab40a0f032a205edf6",
"revision": "12e33f70aeccca27a275b3fa172876a07b891fe8",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="83b27f522642ea573c57e882657ab5c73d4b07f4"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -85,6 +85,46 @@ function defineLazyRegExp(obj, name, pattern) {
});
}
function NetworkInterface(aNetwork) {
let ips = {};
let prefixLengths = {};
aNetwork.getAddresses(ips, prefixLengths);
this.state = aNetwork.state;
this.type = aNetwork.type;
this.name = aNetwork.name;
this.ips = ips.value;
this.prefixLengths = prefixLengths.value;
this.gateways = aNetwork.getGateways();
this.dnses = aNetwork.getDnses();
this.httpProxyHost = aNetwork.httpProxyHost;
this.httpProxyPort = aNetwork.httpProxyPort;
}
NetworkInterface.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
getAddresses: function(aIps, aPrefixLengths) {
aIps.value = this.ips.slice();
aPrefixLengths.value = this.prefixLengths.slice();
return this.ips.length;
},
getGateways: function(aCount) {
if (aCount) {
aCount.value = this.gateways.length;
}
return this.gateways.slice();
},
getDnses: function(aCount) {
if (aCount) {
aCount.value = this.dnses.length;
}
return this.dnses.slice();
}
};
function NetworkInterfaceLinks()
{
this.resetLinks();
@ -254,14 +294,19 @@ NetworkManager.prototype = {
let ips = {};
let prefixLengths = {};
let length = network.getAddresses(ips, prefixLengths);
let promises = [];
for (let i = 0; i < length; i++) {
debug('Adding subnet routes: ' + ips.value[i] + '/' + prefixLengths.value[i]);
gNetworkService.modifyRoute(Ci.nsINetworkService.MODIFY_ROUTE_ADD,
network.name, ips.value[i], prefixLengths.value[i])
.catch((aError) => {
promises.push(
gNetworkService.modifyRoute(Ci.nsINetworkService.MODIFY_ROUTE_ADD,
network.name, ips.value[i], prefixLengths.value[i])
.catch(aError => {
debug("_addSubnetRoutes error: " + aError);
});
}));
}
return Promise.all(promises);
},
updateNetworkInterface: function(network) {
@ -277,46 +322,57 @@ NetworkManager.prototype = {
debug("Network " + network.type + "/" + network.name +
" changed state to " + network.state);
// Keep a copy of network in case it is modified while we are updating.
let networkInterface = new NetworkInterface(network);
// Note that since Lollipop we need to allocate and initialize
// something through netd, so we add createNetwork/destroyNetwork
// to deal with that explicitly.
switch (network.state) {
switch (networkInterface.state) {
case Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED:
gNetworkService.createNetwork(network.name, () => {
this._createNetwork(networkInterface.name)
// Remove pre-created default route and let setAndConfigureActive()
// to set default route only on preferred network
gNetworkService.removeDefaultRoute(network);
.then(() => this._removeDefaultRoute(networkInterface))
// Set DNS server as early as possible to prevent from
// premature domain name lookup.
gNetworkService.setDNS(network, () => {
.then(() => this._setDNS(networkInterface))
.then(() => {
// Add host route for data calls
if (this.isNetworkTypeMobile(network.type)) {
let currentInterfaceLinks = this.networkInterfaceLinks[networkId];
let newLinkRoutes = network.getDnses().concat(network.httpProxyHost);
// If gateways have changed, remove all old routes first.
this._handleGateways(networkId, network.getGateways())
.then(() => this._updateRoutes(currentInterfaceLinks.linkRoutes,
newLinkRoutes,
network.getGateways(), network.name))
.then(() => currentInterfaceLinks.setLinks(newLinkRoutes,
network.getGateways(),
network.name));
if (!this.isNetworkTypeMobile(networkInterface.type)) {
return;
}
let currentInterfaceLinks = this.networkInterfaceLinks[networkId];
let newLinkRoutes = networkInterface.getDnses().concat(
networkInterface.httpProxyHost);
// If gateways have changed, remove all old routes first.
return this._handleGateways(networkId, networkInterface.getGateways())
.then(() => this._updateRoutes(currentInterfaceLinks.linkRoutes,
newLinkRoutes,
networkInterface.getGateways(),
networkInterface.name))
.then(() => currentInterfaceLinks.setLinks(newLinkRoutes,
networkInterface.getGateways(),
networkInterface.name));
})
.then(() => {
if (networkInterface.type !=
Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
return;
}
// Dun type is a special case where we add the default route to a
// secondary table.
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
this.setSecondaryDefaultRoute(network);
}
this._addSubnetRoutes(network);
this.setAndConfigureActive();
return this.setSecondaryDefaultRoute(networkInterface);
})
.then(() => this._addSubnetRoutes(networkInterface))
.then(() => this.setAndConfigureActive())
.then(() => {
// Update data connection when Wifi connected/disconnected
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI && this.mRil) {
if (networkInterface.type ==
Ci.nsINetworkInterface.NETWORK_TYPE_WIFI && this.mRil) {
for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
this.mRil.getRadioInterface(i).updateRILNetworkInterface();
}
@ -325,53 +381,73 @@ NetworkManager.prototype = {
// Probing the public network accessibility after routing table is ready
CaptivePortalDetectionHelper
.notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active);
})
.then(() => {
// Notify outer modules like MmsService to start the transaction after
// the configuration of the network interface is done.
Services.obs.notifyObservers(network, TOPIC_CONNECTION_STATE_CHANGED,
this.convertConnectionType(network));
})
.catch(aError => {
debug("updateNetworkInterface error: " + aError);
});
});
break;
case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
// Remove host route for data calls
if (this.isNetworkTypeMobile(network.type)) {
this._cleanupAllHostRoutes(networkId);
}
// Remove secondary default route for dun.
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
this.removeSecondaryDefaultRoute(network);
}
// Remove routing table in /proc/net/route
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
gNetworkService.resetRoutingTable(network);
} else if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
gNetworkService.removeDefaultRoute(network);
}
// Clear http proxy on active network.
if (this.active && network.type == this.active.type) {
this.clearNetworkProxy();
}
Promise.resolve()
.then(() => {
if (!this.isNetworkTypeMobile(networkInterface.type)) {
return;
}
// Remove host route for data calls
return this._cleanupAllHostRoutes(networkId);
})
.then(() => {
if (networkInterface.type !=
Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
return;
}
// Remove secondary default route for dun.
return this.removeSecondaryDefaultRoute(networkInterface);
})
.then(() => {
if (networkInterface.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
// Remove routing table in /proc/net/route
return this._resetRoutingTable(networkInterface);
}
if (networkInterface.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
return this._removeDefaultRoute(networkInterface)
}
})
.then(() => {
// Clear http proxy on active network.
if (this.active && networkInterface.type == this.active.type) {
this.clearNetworkProxy();
}
// Abort ongoing captive portal detection on the wifi interface
CaptivePortalDetectionHelper
.notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, network);
this.setAndConfigureActive();
// Update data connection when Wifi connected/disconnected
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI && this.mRil) {
for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
this.mRil.getRadioInterface(i).updateRILNetworkInterface();
}
}
gNetworkService.destroyNetwork(network.name, () => {
// Notify outer modules like MmsService to start the transaction after
// the configuration of the network interface is done.
Services.obs.notifyObservers(network, TOPIC_CONNECTION_STATE_CHANGED,
this.convertConnectionType(network));
});
// Abort ongoing captive portal detection on the wifi interface
CaptivePortalDetectionHelper
.notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, networkInterface);
})
.then(() => this.setAndConfigureActive())
.then(() => {
// Update data connection when Wifi connected/disconnected
if (networkInterface.type ==
Ci.nsINetworkInterface.NETWORK_TYPE_WIFI && this.mRil) {
for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
this.mRil.getRadioInterface(i).updateRILNetworkInterface();
}
}
})
.then(() => this._destroyNetwork(networkInterface.name))
.then(() => {
// Notify outer modules like MmsService to start the transaction after
// the configuration of the network interface is done.
Services.obs.notifyObservers(network, TOPIC_CONNECTION_STATE_CHANGED,
this.convertConnectionType(network));
})
.catch(aError => {
debug("updateNetworkInterface error: " + aError);
});
break;
}
},
@ -599,45 +675,86 @@ NetworkManager.prototype = {
return null;
},
_setSecondaryRoute: function(aDoAdd, aInterfaceName, aRoute) {
return new Promise((aResolve, aReject) => {
if (aDoAdd) {
gNetworkService.addSecondaryRoute(aInterfaceName, aRoute,
(aSuccess) => {
if (!aSuccess) {
aReject("addSecondaryRoute failed");
return;
}
aResolve();
});
} else {
gNetworkService.removeSecondaryRoute(aInterfaceName, aRoute,
(aSuccess) => {
if (!aSuccess) {
debug("removeSecondaryRoute failed")
}
// Always resolve.
aResolve();
});
}
});
},
setSecondaryDefaultRoute: function(network) {
let gateways = network.getGateways();
let promises = [];
for (let i = 0; i < gateways.length; i++) {
let isIPv6 = (gateways[i].indexOf(":") != -1) ? true : false;
// First, we need to add a host route to the gateway in the secondary
// routing table to make the gateway reachable. Host route takes the max
// prefix and gateway address 'any'.
let route = {
let hostRoute = {
ip: gateways[i],
prefix: isIPv6 ? IPV6_MAX_PREFIX_LENGTH : IPV4_MAX_PREFIX_LENGTH,
gateway: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY
};
gNetworkService.addSecondaryRoute(network.name, route);
// Now we can add the default route through gateway. Default route takes the
// min prefix and destination ip 'any'.
route.ip = isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY;
route.prefix = 0;
route.gateway = gateways[i];
gNetworkService.addSecondaryRoute(network.name, route);
}
},
removeSecondaryDefaultRoute: function(network) {
let gateways = network.getGateways();
for (let i = 0; i < gateways.length; i++) {
let isIPv6 = (gateways[i].indexOf(":") != -1) ? true : false;
// Remove both default route and host route.
let route = {
let defaultRoute = {
ip: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY,
prefix: 0,
gateway: gateways[i]
};
gNetworkService.removeSecondaryRoute(network.name, route);
route.ip = gateways[i];
route.prefix = isIPv6 ? IPV6_MAX_PREFIX_LENGTH : IPV4_MAX_PREFIX_LENGTH;
route.gateway = isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY;
gNetworkService.removeSecondaryRoute(network.name, route);
let promise = this._setSecondaryRoute(true, network.name, hostRoute)
.then(() => this._setSecondaryRoute(true, network.name, defaultRoute));
promises.push(promise);
}
return Promise.all(promises);
},
removeSecondaryDefaultRoute: function(network) {
let gateways = network.getGateways();
let promises = [];
for (let i = 0; i < gateways.length; i++) {
let isIPv6 = (gateways[i].indexOf(":") != -1) ? true : false;
// Remove both default route and host route.
let defaultRoute = {
ip: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY,
prefix: 0,
gateway: gateways[i]
};
let hostRoute = {
ip: gateways[i],
prefix: isIPv6 ? IPV6_MAX_PREFIX_LENGTH : IPV4_MAX_PREFIX_LENGTH,
gateway: isIPv6 ? IPV6_ADDRESS_ANY : IPV4_ADDRESS_ANY
};
let promise = this._setSecondaryRoute(false, network.name, defaultRoute)
.then(() => this._setSecondaryRoute(false, network.name, hostRoute));
promises.push(promise);
}
return Promise.all(promises);
},
/**
@ -664,8 +781,7 @@ NetworkManager.prototype = {
this.active.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED &&
this.active.type == this._preferredNetworkType) {
debug("Active network is already our preferred type.");
this._setDefaultRouteAndProxy(this.active, oldActive);
return;
return this._setDefaultRouteAndProxy(this.active, oldActive);
}
// Find a suitable network interface to activate.
@ -688,28 +804,33 @@ NetworkManager.prototype = {
}
}
if (this.active) {
// Give higher priority to default data APN than secondary APN.
// If default data APN is not connected, we still set default route
// and DNS on secondary APN.
if (defaultDataNetwork &&
this.isNetworkTypeSecondaryMobile(this.active.type) &&
this.active.type != this.preferredNetworkType) {
this.active = defaultDataNetwork;
}
// Don't set default route on secondary APN
if (!this.isNetworkTypeSecondaryMobile(this.active.type)) {
this._setDefaultRouteAndProxy(this.active, oldActive);
}
// Give higher priority to default data APN than secondary APN.
// If default data APN is not connected, we still set default route
// and DNS on secondary APN.
if (this.active && defaultDataNetwork &&
this.isNetworkTypeSecondaryMobile(this.active.type) &&
this.active.type != this.preferredNetworkType) {
this.active = defaultDataNetwork;
}
if (this.active != oldActive) {
Services.obs.notifyObservers(this.active, TOPIC_ACTIVE_CHANGED, null);
}
return Promise.resolve()
.then(() => {
// Don't set default route on secondary APN
if (!this.active || this.isNetworkTypeSecondaryMobile(this.active.type)) {
return Promise.resolve();
}
if (this._manageOfflineStatus) {
Services.io.offline = !this.active;
}
return this._setDefaultRouteAndProxy(this.active, oldActive);
})
.then(() => {
if (this.active != oldActive) {
Services.obs.notifyObservers(this.active, TOPIC_ACTIVE_CHANGED, null);
}
if (this._manageOfflineStatus) {
Services.io.offline = !this.active;
}
});
},
resolveHostname: function(network, hostname) {
@ -788,13 +909,78 @@ NetworkManager.prototype = {
}
},
_setDefaultRouteAndProxy: function(network, oldInterface) {
gNetworkService.setDefaultRoute(network, oldInterface, (success) => {
if (!success) {
gNetworkService.destroyNetwork(network, function() {});
return;
}
this.setNetworkProxy(network);
_setDNS: function(aNetwork) {
return new Promise((aResolve, aReject) => {
gNetworkService.setDNS(aNetwork, (aError) => {
if (aError) {
aReject("setDNS failed");
return;
}
aResolve();
});
});
},
_createNetwork: function(aInterfaceName) {
return new Promise((aResolve, aReject) => {
gNetworkService.createNetwork(aInterfaceName, (aSuccess) => {
if (!aSuccess) {
aReject("createNetwork failed");
return;
}
aResolve();
});
});
},
_destroyNetwork: function(aInterfaceName) {
return new Promise((aResolve, aReject) => {
gNetworkService.destroyNetwork(aInterfaceName, (aSuccess) => {
if (!aSuccess) {
debug("destroyNetwork failed")
}
// Always resolve.
aResolve();
});
});
},
_resetRoutingTable: function(aNetwork) {
return new Promise((aResolve, aReject) => {
gNetworkService.resetRoutingTable(aNetwork, (aSuccess) => {
if (!aSuccess) {
debug("resetRoutingTable failed");
}
// Always resolve.
aResolve();
});
});
},
_removeDefaultRoute: function(aNetwork) {
return new Promise((aResolve, aReject) => {
gNetworkService.removeDefaultRoute(aNetwork, (aSuccess) => {
if (!aSuccess) {
debug("removeDefaultRoute failed");
}
// Always resolve.
aResolve();
});
});
},
_setDefaultRouteAndProxy: function(aNetwork, aOldInterface) {
return new Promise((aResolve, aReject) => {
gNetworkService.setDefaultRoute(aNetwork, aOldInterface, (aSuccess) => {
if (!aSuccess) {
gNetworkService.destroyNetwork(aNetwork, function() {
aReject("setDefaultRoute failed");
});
return;
}
this.setNetworkProxy(aNetwork);
aResolve();
});
});
},

View File

@ -368,13 +368,15 @@ NetworkService.prototype = {
});
},
resetRoutingTable: function(network) {
resetRoutingTable: function(network, callback) {
let options = {
cmd: "removeNetworkRoute",
ifname: network.name
};
this.controlMessage(options);
this.controlMessage(options, function(result) {
callback.nativeCommandResult(!result.error);
});
},
setDNS: function(networkInterface, callback) {
@ -406,7 +408,7 @@ NetworkService.prototype = {
});
},
removeDefaultRoute: function(network) {
removeDefaultRoute: function(network, callback) {
debug("Remove default route for " + network.name);
let gateways = network.getGateways();
let options = {
@ -414,7 +416,9 @@ NetworkService.prototype = {
ifname: network.name,
gateways: gateways
};
this.controlMessage(options);
this.controlMessage(options, function(result) {
callback.nativeCommandResult(!result.error);
});
},
_routeToString: function(interfaceName, host, prefixLength, gateway) {
@ -487,7 +491,7 @@ NetworkService.prototype = {
});
},
addSecondaryRoute: function(ifname, route) {
addSecondaryRoute: function(ifname, route, callback) {
debug("Going to add route to secondary table on " + ifname);
let options = {
cmd: "addSecondaryRoute",
@ -496,10 +500,12 @@ NetworkService.prototype = {
prefix: route.prefix,
gateway: route.gateway
};
this.controlMessage(options);
this.controlMessage(options, function(result) {
callback.nativeCommandResult(!result.error);
});
},
removeSecondaryRoute: function(ifname, route) {
removeSecondaryRoute: function(ifname, route, callback) {
debug("Going to remove route from secondary table on " + ifname);
let options = {
cmd: "removeSecondaryRoute",
@ -508,7 +514,9 @@ NetworkService.prototype = {
prefix: route.prefix,
gateway: route.gateway
};
this.controlMessage(options);
this.controlMessage(options, function(result) {
callback.nativeCommandResult(!result.error);
});
},
// Enable/Disable DHCP server.

View File

@ -2703,13 +2703,13 @@ DataCall.prototype = {
if (this.state == RIL.GECKO_NETWORK_STATE_CONNECTED) {
// This needs to run asynchronously, to behave the same way as the case of
// non-shared apn, see bug 1059110.
Services.tm.currentThread.dispatch(function(state) {
Services.tm.currentThread.dispatch(() => {
// Do not notify if state changed while this event was being dispatched,
// the state probably was notified already or need not to be notified.
if (networkInterface.state == state) {
if (networkInterface.state == RIL.GECKO_NETWORK_STATE_CONNECTED) {
networkInterface.notifyRILNetworkInterface();
}
}.bind(null, RIL.GECKO_NETWORK_STATE_CONNECTED), Ci.nsIEventTarget.DISPATCH_NORMAL);
}, Ci.nsIEventTarget.DISPATCH_NORMAL);
return;
}
@ -2829,13 +2829,15 @@ DataCall.prototype = {
// Notify the DISCONNECTED event immediately after network interface is
// removed from requestedNetworkIfaces, to make the DataCall, shared or
// not, to have the same behavior.
Services.tm.currentThread.dispatch(function(state) {
Services.tm.currentThread.dispatch(() => {
// Do not notify if state changed while this event was being dispatched,
// the state probably was notified already or need not to be notified.
if (networkInterface.state == state) {
if (networkInterface.state == RIL.GECKO_NETWORK_STATE_DISCONNECTED) {
networkInterface.notifyRILNetworkInterface();
// Clear link info after notifying NetworkManager.
this.resetLinkInfo();
}
}.bind(null, RIL.GECKO_NETWORK_STATE_DISCONNECTED), Ci.nsIEventTarget.DISPATCH_NORMAL);
}, Ci.nsIEventTarget.DISPATCH_NORMAL);
}
// Only deactivate data call if no more network interface needs this
@ -2861,7 +2863,6 @@ DataCall.prototype = {
}, this.onDeactivateDataCallResult.bind(this));
this.state = RIL.GECKO_NETWORK_STATE_DISCONNECTING;
this.resetLinkInfo();
},
// Entry method for timer events. Used to reconnect to a failed APN

View File

@ -159,7 +159,7 @@ interface nsIDhcpRequestCallback : nsISupports
/**
* Provide network services.
*/
[scriptable, uuid(2e030f00-8b74-4800-8add-5862ab183503)]
[scriptable, uuid(8216224c-a4e0-43fa-9662-3f2446b500c6)]
interface nsINetworkService : nsISupports
{
const long MODIFY_ROUTE_ADD = 0;
@ -271,7 +271,8 @@ interface nsINetworkService : nsISupports
* @param networkInterface
* The network interface we want remove from the routing table.
*/
void resetRoutingTable(in nsINetworkInterface networkInterface);
void resetRoutingTable(in nsINetworkInterface networkInterface,
in nsINativeCommandCallback callback);
/**
* Set DNS.
@ -305,7 +306,8 @@ interface nsINetworkService : nsISupports
* @param networkInterface
* The network interface we want remove from the default route.
*/
void removeDefaultRoute(in nsINetworkInterface networkInterface);
void removeDefaultRoute(in nsINetworkInterface networkInterface,
in nsINativeCommandCallback callback);
/**
* Modify route.
@ -342,7 +344,8 @@ interface nsINetworkService : nsISupports
* .prefix: destination prefix
* .gateway: gateway ip address
*/
void addSecondaryRoute(in DOMString interfaceName, in jsval route);
void addSecondaryRoute(in DOMString interfaceName, in jsval route,
in nsINativeCommandCallback callback);
/**
* Remove route from secondary routing table.
@ -355,7 +358,8 @@ interface nsINetworkService : nsISupports
* .prefix: destination prefix
* .gateway: gateway ip address
*/
void removeSecondaryRoute(in DOMString interfaceName, in jsval route);
void removeSecondaryRoute(in DOMString interfaceName, in jsval route,
in nsINativeCommandCallback callback);
/**
* Enable or disable usb rndis.

View File

@ -31,7 +31,8 @@ class nsScreenGonk : public nsBaseScreen
typedef mozilla::hal::ScreenConfiguration ScreenConfiguration;
public:
nsScreenGonk();
nsScreenGonk(uint32_t aId, ANativeWindow* aNativeWindow);
~nsScreenGonk();
NS_IMETHOD GetId(uint32_t* aId);
@ -42,9 +43,14 @@ public:
NS_IMETHOD GetRotation(uint32_t* aRotation);
NS_IMETHOD SetRotation(uint32_t aRotation);
uint32_t GetId();
nsIntRect GetRect();
float GetDpi();
ANativeWindow* GetNativeWindow();
nsIntRect GetNaturalBounds();
uint32_t EffectiveScreenRotation();
ScreenConfiguration GetConfiguration();
bool IsPrimaryScreen();
void RegisterWindow(nsWindow* aWindow);
void UnregisterWindow(nsWindow* aWindow);
@ -56,8 +62,12 @@ public:
}
protected:
nsIntRect mScreenBounds;
nsIntRect mVirtualBounds;
uint32_t mId;
int32_t mColorDepth;
android::sp<ANativeWindow> mNativeWindow;
float mDpi;
nsIntRect mNaturalBounds; // Screen bounds w/o rotation taken into account.
nsIntRect mVirtualBounds; // Screen bounds w/ rotation taken into account.
uint32_t mScreenRotation;
uint32_t mPhysicalScreenRotation;
nsTArray<nsWindow*> mTopWindows;
@ -65,6 +75,15 @@ protected:
class nsScreenManagerGonk final : public nsIScreenManager
{
public:
enum {
// TODO: Bug 1138287 will define more screen/display types.
PRIMARY_SCREEN_TYPE = 0,
// TODO: Maintain a mapping from type to id dynamically.
PRIMARY_SCREEN_ID = 0,
};
public:
nsScreenManagerGonk();
@ -77,12 +96,16 @@ public:
void Initialize();
void DisplayEnabled(bool aEnabled);
void AddScreen(uint32_t aDisplayType);
void RemoveScreen(uint32_t aDisplayType);
protected:
~nsScreenManagerGonk();
void VsyncControl(bool aEnabled);
uint32_t GetIdFromType(uint32_t aDisplayType);
bool mInitialized;
nsCOMPtr<nsIScreen> mOneScreen;
nsTArray<nsRefPtr<nsScreenGonk>> mScreens;
nsRefPtr<nsRunnable> mScreenOnEvent;
nsRefPtr<nsRunnable> mScreenOffEvent;
};

View File

@ -134,7 +134,6 @@ nsWindow::nsWindow()
nsRefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance();
screenManager->Initialize();
mScreen = nsScreenManagerGonk::GetPrimaryScreen();
// This is a hack to force initialization of the compositor
// resources, if we're going to use omtc.
@ -150,7 +149,9 @@ nsWindow::nsWindow()
nsWindow::~nsWindow()
{
HwcComposer2D::GetInstance()->SetCompositorParent(nullptr);
if (mScreen->IsPrimaryScreen()) {
HwcComposer2D::GetInstance()->SetCompositorParent(nullptr);
}
}
void
@ -397,11 +398,17 @@ nsWindow::Create(nsIWidget *aParent,
const nsIntRect &aRect,
nsWidgetInitData *aInitData)
{
nsIntRect virtualBounds;
mScreen->GetRect(&virtualBounds.x, &virtualBounds.y,
&virtualBounds.width, &virtualBounds.height);
BaseCreate(aParent, IS_TOPLEVEL() ? virtualBounds : aRect,
aInitData);
BaseCreate(aParent, aRect, aInitData);
nsCOMPtr<nsIScreen> screen;
uint32_t screenId = aParent ? ((nsWindow*)aParent)->mScreen->GetId() :
aInitData->mScreenId;
nsRefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance();
screenManager->ScreenForId(screenId, getter_AddRefs(screen));
mScreen = static_cast<nsScreenGonk*>(screen.get());
mBounds = aRect;
@ -409,7 +416,7 @@ nsWindow::Create(nsIWidget *aParent,
mVisible = false;
if (!aParent) {
mBounds = virtualBounds;
mBounds = mScreen->GetRect();
}
if (!IS_TOPLEVEL()) {
@ -418,7 +425,8 @@ nsWindow::Create(nsIWidget *aParent,
mScreen->RegisterWindow(this);
Resize(0, 0, virtualBounds.width, virtualBounds.height, false);
Resize(0, 0, mBounds.width, mBounds.height, false);
return NS_OK;
}
@ -511,10 +519,7 @@ nsWindow::Resize(double aX,
}
if (aRepaint) {
nsIntRect virtualBounds;
mScreen->GetRect(&virtualBounds.x, &virtualBounds.y,
&virtualBounds.width, &virtualBounds.height);
Invalidate(virtualBounds);
Invalidate(mBounds);
}
return NS_OK;
@ -538,7 +543,12 @@ nsWindow::SetFocus(bool aRaise)
if (aRaise) {
BringToTop();
}
gFocusedWindow = this;
if (!IS_TOPLEVEL() && mScreen->IsPrimaryScreen()) {
// We should only set focused window on non-toplevel primary window.
gFocusedWindow = this;
}
return NS_OK;
}
@ -587,7 +597,7 @@ nsWindow::GetNativeData(uint32_t aDataType)
switch (aDataType) {
case NS_NATIVE_WINDOW:
// Called before primary display's EGLSurface creation.
return GetGonkDisplay()->GetNativeWindow();
return mScreen->GetNativeWindow();
}
return nullptr;
}
@ -748,7 +758,7 @@ nsWindow::EndRemoteDrawing()
float
nsWindow::GetDPI()
{
return GetGonkDisplay()->xdpi;
return mScreen->GetDpi();
}
double
@ -803,7 +813,7 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
}
CreateCompositor();
if (mCompositorParent) {
if (mCompositorParent && mScreen->IsPrimaryScreen()) {
HwcComposer2D::GetInstance()->SetCompositorParent(mCompositorParent);
}
MOZ_ASSERT(mLayerManager);
@ -826,10 +836,7 @@ nsWindow::BringToTop()
mWidgetListener->WindowActivated();
}
nsIntRect virtualBounds;
mScreen->GetRect(&virtualBounds.x, &virtualBounds.y,
&virtualBounds.width, &virtualBounds.height);
Invalidate(virtualBounds);
Invalidate(mBounds);
}
void
@ -874,42 +881,75 @@ nsWindow::NeedsPaint()
Composer2D*
nsWindow::GetComposer2D()
{
if (!mScreen->IsPrimaryScreen()) {
return nullptr;
}
return HwcComposer2D::GetInstance();
}
static uint32_t
SurfaceFormatToColorDepth(int32_t aSurfaceFormat)
{
switch (aSurfaceFormat) {
case GGL_PIXEL_FORMAT_RGB_565:
return 16;
case GGL_PIXEL_FORMAT_RGBA_8888:
return 32;
}
return 24; // GGL_PIXEL_FORMAT_RGBX_8888
}
// nsScreenGonk.cpp
nsScreenGonk::nsScreenGonk()
: mScreenRotation(nsIScreen::ROTATION_0_DEG)
nsScreenGonk::nsScreenGonk(uint32_t aId, ANativeWindow* aNativeWindow)
: mId(aId)
, mNativeWindow(aNativeWindow)
, mScreenRotation(nsIScreen::ROTATION_0_DEG)
, mPhysicalScreenRotation(nsIScreen::ROTATION_0_DEG)
{
nsIntSize screenSize;
ANativeWindow *win = GetGonkDisplay()->GetNativeWindow();
if (win->query(win, NATIVE_WINDOW_WIDTH, &screenSize.width) ||
win->query(win, NATIVE_WINDOW_HEIGHT, &screenSize.height)) {
int surfaceFormat;
if (mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &mVirtualBounds.width) ||
mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &mVirtualBounds.height) ||
mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_FORMAT, &surfaceFormat)) {
NS_RUNTIMEABORT("Failed to get native window size, aborting...");
}
mScreenBounds = gfx::IntRect(gfx::IntPoint(0, 0), screenSize);
char propValue[PROPERTY_VALUE_MAX];
property_get("ro.sf.hwrotation", propValue, "0");
mPhysicalScreenRotation = atoi(propValue) / 90;
mNaturalBounds = mVirtualBounds;
mVirtualBounds = mScreenBounds;
if (IsPrimaryScreen()) {
char propValue[PROPERTY_VALUE_MAX];
property_get("ro.sf.hwrotation", propValue, "0");
mPhysicalScreenRotation = atoi(propValue) / 90;
}
mDpi = GetGonkDisplay()->xdpi;
mColorDepth = SurfaceFormatToColorDepth(surfaceFormat);
}
nsScreenGonk::~nsScreenGonk()
{
}
bool
nsScreenGonk::IsPrimaryScreen()
{
return nsScreenManagerGonk::PRIMARY_SCREEN_ID == mId;
}
NS_IMETHODIMP
nsScreenGonk::GetId(uint32_t *outId)
{
*outId = 1;
*outId = mId;
return NS_OK;
}
uint32_t
nsScreenGonk::GetId()
{
return mId;
}
NS_IMETHODIMP
nsScreenGonk::GetRect(int32_t *outLeft, int32_t *outTop,
int32_t *outWidth, int32_t *outHeight)
@ -923,6 +963,12 @@ nsScreenGonk::GetRect(int32_t *outLeft, int32_t *outTop,
return NS_OK;
}
nsIntRect
nsScreenGonk::GetRect()
{
return mVirtualBounds;
}
NS_IMETHODIMP
nsScreenGonk::GetAvailRect(int32_t *outLeft, int32_t *outTop,
int32_t *outWidth, int32_t *outHeight)
@ -930,31 +976,20 @@ nsScreenGonk::GetAvailRect(int32_t *outLeft, int32_t *outTop,
return GetRect(outLeft, outTop, outWidth, outHeight);
}
static uint32_t
ColorDepth()
{
switch (GetGonkDisplay()->surfaceformat) {
case GGL_PIXEL_FORMAT_RGB_565:
return 16;
case GGL_PIXEL_FORMAT_RGBA_8888:
return 32;
}
return 24; // GGL_PIXEL_FORMAT_RGBX_8888
}
NS_IMETHODIMP
nsScreenGonk::GetPixelDepth(int32_t *aPixelDepth)
{
// XXX: this should actually return 32 when we're using 24-bit
// color, because we use RGBX.
*aPixelDepth = ColorDepth();
*aPixelDepth = mColorDepth;
return NS_OK;
}
NS_IMETHODIMP
nsScreenGonk::GetColorDepth(int32_t *aColorDepth)
{
return GetPixelDepth(aColorDepth);
*aColorDepth = mColorDepth;
return NS_OK;
}
NS_IMETHODIMP
@ -964,6 +999,18 @@ nsScreenGonk::GetRotation(uint32_t* aRotation)
return NS_OK;
}
float
nsScreenGonk::GetDpi()
{
return mDpi;
}
ANativeWindow*
nsScreenGonk::GetNativeWindow()
{
return mNativeWindow.get();
}
NS_IMETHODIMP
nsScreenGonk::SetRotation(uint32_t aRotation)
{
@ -980,10 +1027,10 @@ nsScreenGonk::SetRotation(uint32_t aRotation)
if (rotation == nsIScreen::ROTATION_90_DEG ||
rotation == nsIScreen::ROTATION_270_DEG) {
mVirtualBounds = nsIntRect(0, 0,
mScreenBounds.height,
mScreenBounds.width);
mNaturalBounds.height,
mNaturalBounds.width);
} else {
mVirtualBounds = mScreenBounds;
mVirtualBounds = mNaturalBounds;
}
nsAppShell::NotifyScreenRotation();
@ -1000,7 +1047,7 @@ nsScreenGonk::SetRotation(uint32_t aRotation)
nsIntRect
nsScreenGonk::GetNaturalBounds()
{
return mScreenBounds;
return mNaturalBounds;
}
uint32_t
@ -1039,12 +1086,12 @@ ScreenConfiguration
nsScreenGonk::GetConfiguration()
{
ScreenOrientation orientation = ComputeOrientation(mScreenRotation,
mScreenBounds.Size());
uint32_t colorDepth = ColorDepth();
mNaturalBounds.Size());
// NB: perpetuating colorDepth == pixelDepth illusion here, for
// consistency.
return ScreenConfiguration(mVirtualBounds, orientation,
colorDepth, colorDepth);
mColorDepth, mColorDepth);
}
void
@ -1071,7 +1118,6 @@ NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager)
nsScreenManagerGonk::nsScreenManagerGonk()
: mInitialized(false)
{
mOneScreen = new nsScreenGonk();
}
nsScreenManagerGonk::~nsScreenManagerGonk()
@ -1110,6 +1156,8 @@ nsScreenManagerGonk::Initialize()
mScreenOffEvent = new ScreenOnOffEvent(false);
GetGonkDisplay()->OnEnabled(displayEnabledCallback);
AddScreen(PRIMARY_SCREEN_TYPE);
nsAppShell::NotifyScreenInitialized();
mInitialized = true;
}
@ -1127,7 +1175,7 @@ nsScreenManagerGonk::DisplayEnabled(bool aEnabled)
NS_IMETHODIMP
nsScreenManagerGonk::GetPrimaryScreen(nsIScreen **outScreen)
{
NS_IF_ADDREF(*outScreen = mOneScreen.get());
NS_IF_ADDREF(*outScreen = mScreens[0].get());
return NS_OK;
}
@ -1135,7 +1183,15 @@ NS_IMETHODIMP
nsScreenManagerGonk::ScreenForId(uint32_t aId,
nsIScreen **outScreen)
{
return GetPrimaryScreen(outScreen);
for (size_t i = 0; i < mScreens.Length(); i++) {
if (mScreens[i]->GetId() == aId) {
NS_IF_ADDREF(*outScreen = mScreens[i].get());
return NS_OK;
}
}
*outScreen = nullptr;
return NS_OK;
}
NS_IMETHODIMP
@ -1145,19 +1201,29 @@ nsScreenManagerGonk::ScreenForRect(int32_t inLeft,
int32_t inHeight,
nsIScreen **outScreen)
{
// Since all screens have independent coordinate system, we could
// only return the primary screen no matter what rect is given.
return GetPrimaryScreen(outScreen);
}
NS_IMETHODIMP
nsScreenManagerGonk::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen)
{
return GetPrimaryScreen(outScreen);
for (size_t i = 0; i < mScreens.Length(); i++) {
if (aWidget == mScreens[i]->GetNativeWindow()) {
NS_IF_ADDREF(*outScreen = mScreens[i].get());
return NS_OK;
}
}
*outScreen = nullptr;
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerGonk::GetNumberOfScreens(uint32_t *aNumberOfScreens)
{
*aNumberOfScreens = 1;
*aNumberOfScreens = mScreens.Length();
return NS_OK;
}
@ -1189,3 +1255,39 @@ nsScreenManagerGonk::VsyncControl(bool aEnabled)
display.DisableVsync();
}
}
uint32_t
nsScreenManagerGonk::GetIdFromType(uint32_t aDisplayType)
{
// This is the only place where we make the assumption that
// display type is equivalent to screen id.
// Bug 1138287 will address the conversion from type to id.
return aDisplayType;
}
void
nsScreenManagerGonk::AddScreen(uint32_t aDisplayType)
{
// We currently only support adding primary screen.
MOZ_ASSERT(PRIMARY_SCREEN_TYPE == aDisplayType);
uint32_t id = GetIdFromType(aDisplayType);
ANativeWindow* win = GetGonkDisplay()->GetNativeWindow();
nsScreenGonk* screen = new nsScreenGonk(id, win);
mScreens.AppendElement(screen);
}
void
nsScreenManagerGonk::RemoveScreen(uint32_t aDisplayType)
{
uint32_t screenId = GetIdFromType(aDisplayType);
for (size_t i = 0; i < mScreens.Length(); i++) {
if (mScreens[i]->GetId() == screenId) {
mScreens.RemoveElementAt(i);
break;
}
}
}