Android Development Usb Transfer - android

I am fairly new to Android Development and i have recently been exploring Usb Host.
Would anyone be able to tell me how to use Bulk Transfer so that i can see what an external camera sees but instead show it on my tablet?
Camera : Canon Powershot A1300
Tablet : Iconia A200
I have looked around stack overflow and some other forums but have not yet been able to find a good explanation on how to use Bulk Transfer or what constants to use as parameters for retrieving certain data.
I am able to see the endpoints and set up a connection with the external camera but I do not know where to go from here.
Any help is deeply appreciated.

The USB Host APIs in Android are fairly thin, by which I mean once you have gone beyond enumerating the interfaces/endpoints and creating a connection it doesn't do much more to assist you. You are then in the realm of communicating with raw USB data transfers, the format of which depend on the device class your camera represents. Your request is somewhat a can of worms, so I will do my best to provide helpful resources.
Unfortunately, storage and media devices are not the simplest device classes to interpret, so it may be difficult if you are just getting your feet wet on USB in general. The best advice I can give is to take a look at the device class specs for the interface class your camera reports (most are either Mass Storage or MTP), which can be found here: http://www.usb.org/developers/devclass_docs
The spec document will enumerate the commands you need to use to communicate with the device. I would also recommend checking out USB In a Nutshell, which does a great job of pointing out how USB requests are constructed in general, which can help you map what you see in a the spec docs to the parameters found in the methods of UsbDeviceConnection: http://www.beyondlogic.org/usbnutshell/usb1.shtml
There will likely be a handful of control commands you need to send to "endpoint 0" initially to set up the camera, and then the remaining transfers will likely take place over the bulk endpoints.
In Android terms, control requests can only be sent synchronously using UsbDeviceConnection.controlTransfer(), meaning this method blocks until the transfer is complete. The parameters that fill in this method are found in the spec docs for your device class.
Requests on bulk endpoints can be sent synchronously via UsbDeviceConnection.bulkTransfer() OR asynchronously using a UsbRequest instance. With UsbRequest you can queue a transfer and then later check back (via UsbDeviceConnection.requestWait()) for the results.
I have some examples on my Github page in using the host APIs to do some basic interrupt and control transfers to get information like device descriptors. Perhaps some of that will be helpful to you as well: https://github.com/devunwired/accessory-samples
With regards to your question about the USB example code:
The request made in this code is just a generic "Get Configuration Descriptor" request that all USB devices must respond to (it's a core command, not class-specific). In fact, its the request where the Android APIs get the information you can query for interfaces and endpoints. The field values come from the Core USB Specification (this command specifically is defined at section 9.4.3 and 9.6.3 in the 3.0 spec): http://www.usb.org/developers/docs/ or a more helpful description you can find from USB in a Nutshell, which has a little more discussion: http://www.beyondlogic.org/usbnutshell/usb5.shtml#ConfigurationDescriptors
The length is somewhat arbitrary, this tells the driver how many bytes to read or write. Most USB host drivers will first query the device descriptor, which includes a field telling the host the Max Packet Size the device supports, and then will use that size as the length for future requests. A full-featured driver would probably make this command and then check the length bytes first (the wTotalLength field of the descriptor) to see if the buffer was large enough, and modify/resend if not. In the example, I just chose 64 for simplicity because that is the "maximum" Max Packet Size the protocol defines as supportable.
Again, then making requests of the specific data your device has to offer, those commands will be found in the specific class document, not the core specification.

Related

Get serial number or other unique ID of MIDI device?

If I have an Android MidiDevice object, I can get its name or product name like this:
val name = device.info.properties.getString(MidiDeviceInfo.PROPERTY_NAME)
val product = device.info.properties.getString(MidiDeviceInfo.PROPERTY_PRODUCT)
But a request for its serial number always returns null:
val serialNumber = device.info.properties.getString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER)
This is happening with every device I've tried, including virtual MIDI devices, USB MIDI interfaces and Bluetooth MIDI interfaces. Is this working for anyone else? I didn't find any mention of this property in Google, StackOverflow or the Android IssueTracker.
My goal in showing the serial number is to distinguish in the interface between multiple interfaces of the same model. I'm open to other solutions if there's another way to do that.
I can't speak to Android specifically, but it's rare for MIDI interfaces to have such a serial number.
This is a common problem. If you look at the USB device descriptor (using USBTreeView or similar) for multiple of the same model of the device, you'll see that there is often nothing distinguishing between the two.
Additionally, on the MIDI side of things, there is certainly no guarantee of ID/serial as there isn't even a standard for retrieving such information. I think out of all the MIDI devices I own, only one (APC40) has a serial number accessible via SysEx messages.
All this to say, I don't think that property is going to be reliably populated because there is no device-specific information to base it on in most cases. It might have been added to the Android API for something like RTP-MIDI or similar.

Where does 'baud rate' value go in serial Android-2-Arduino communication over USB

Issues with Android-2-Arduino communication made it clear to me I have no clue which parts of the chain are (directly) affected by the baud rate. Could you please confirm/correct following assumptions?
The 'baud rate' value is not related to anything on the Android side. Therefore it is not a bug when an Android USB/Serial library only sends the baud rate value (9600, 125000, etc.) to the other side via controlTransfer, not storing it anywhere, not setting it somehow to the Android device itself.
When calling usbConn.controlTransfer with 'baud rate' parameter on Android, this command is NOT redundant to me calling Serial.init(baudRate) in the Arduino code. Both these calls are intended for different HW/parts. Both of those parts reside on Arduino. (Both, obviously, must be called with identical value.)

filter packet data based on the type of content they carry

I want to filter the packet data based on the type of data they carry. I mean is it possible to recognize whether the packet carries text/audio/video/other type of information by analyzing the packet header or the payload?
Also, I want to be able to do this in real time; so that I can keep track of How much of data has been used up in text/audio/video etc.. Can these things be done using tcpdump? I want to run in a tizen/android phone..
A few things might be needed to achieve this.
In Tizen, you need su access to the device and install tcpdump and a host of other libraries like libpcap for example.
For HTTP you could rely on MIME headers.
You could use pre-defined standard ports in certain cases.
For Audio and Video you could examine the payload and see if the header matches and then classify.
But to generalize it across all data formats is going to take some work beyond simply reusing existing tools like tcpdump.

any way to discover Android devices on your network?

I want to be able to discover Android devices on my network and possibly retrieve some device information about them. This is very easy with Apple devices since they run Bonjour services. However, I can't seem to find any similar service running on Android.
This must work without modifying the Android device, installing some service, or opening some port. It's meant to work with vanilla Android devices in the way that Bonjour helps you find vanilla Apple devices. Even being able to just verify that the device is running Android would be sufficient.
Chosen Answer: Although it's not the top rated answer (yet), please take a look at the response by Luis. As he mentions, you can use a DNS lookup (using your local DNS server) to discover Android devices. I have found this to have a 100% success rate, as Android forces devices to use a hostname of android-_____. This is apparently difficult to change on the phone, even if it is rooted. So I think this is a pretty accurate method. Thanks, Luis!
Example:
$ nslookup 192.168.1.104 192.168.1.1
Server: 192.168.1.1
Address: 192.168.1.1#53
104.1.168.192.in-addr.arpa name = android-711c129e251f14cf.\001.
Sample Code: If you wanted to implement this in Java (e.g., to run on Android), you can't easily use getHostName() because it uses the external DNS servers. You want to use the local DNS server on your router, for example. Luis mentions below that you could modify the DNS servers of the Wifi connection, but that could possibly break other things. Instead, I've found the dnsjava library to be extremely helpful to send targeted DNS requests. Here is some sample code using the library:
String ipAddress = "104.1.168.192";
String dnsblDomain = "in-addr.arpa";
Record[] records;
Lookup lookup = new Lookup(ipAddress + "." + dnsblDomain, Type.PTR);
SimpleResolver resolver = new SimpleResolver();
resolver.setAddress(InetAddress.getByName("192.168.1.1"));
lookup.setResolver(resolver);
records = lookup.run();
if(lookup.getResult() == Lookup.SUCCESSFUL) {
for (int i = 0; i < records.length; i++) {
if(records[i] instanceof PTRRecord) {
PTRRecord ptr = (PTRRecord) records[i];
System.out.println("DNS Record: " + records[0].rdataToString());
}
}
} else {
System.out.println("Failed lookup");
}
} catch(Exception e) {
System.out.println("Exception: " + e);
}
This gives me the output:
DNS Record: android-711c129e251f14cf.\001.
Bingo.
There is an very simple approach that gave me positive results in few different devices.
When a device connects to your router it receives an IP (i.e. DHCP) and registers a name in DNS. The name that is registered seems to be always in the form android_nnnnnnnn.
Of course, you can name any computer with the same approach and trick the check, resulting in false positives ...
Also, I can't ensure that all device suppliers are following the same approach, but I've found it to work correctly in a few devices from different brands (including different SDK levels) that I've tested.
--EDITED--
How to do it
It depends on where you would be running the code to discover the Android devices. Assuming that you would be running the code in an Android device:
First discover devices responding to ping in your network. You can use the code in my answer to this post: execComd() to run a ping command.
Get the name of responding devices using the code:
InetAddress inetAddress = InetAddress.getByName(string_with_ip_addr);
String name = inetAddress.getCanonicalHostName();
--EDIT 2--
Proof of concept
The method below is just a proof of concept for what I've wrote above.
I'm using isReachable() method to generate the ICMP request, which is said to only work with rooted devices in many posts, which is the case for the device used for testing it. However, I didn't give root permissions for the application running this code, so I believe it couldn't set the SIUD bit, which is the reason why some claim that this method fails. I would like to do it here from the perspective of someone testing it on a non-rooted device.
To call use:
ArrayList<String> hosts = scanSubNet("192.168.1.");
It returns in hosts, a list of names for devices responding to ping request.
private ArrayList<String> scanSubNet(String subnet){
ArrayList<String> hosts = new ArrayList<String>();
InetAddress inetAddress = null;
for(int i=1; i<10; i++){
Log.d(TAG, "Trying: " + subnet + String.valueOf(i));
try {
inetAddress = InetAddress.getByName(subnet + String.valueOf(i));
if(inetAddress.isReachable(1000)){
hosts.add(inetAddress.getHostName());
Log.d(TAG, inetAddress.getHostName());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return hosts;
}
Regards.
Android is not going to be as easy as iOS. There is no Bonjour equivalent.
Android 4.0, Ice Cream Sandwich, introduced Wi-Fi Direct Peer to Peer networking. At first I hoped it might be able to be scanned in the the way your thinking, but it helps Android devices communicate without an access point, so they're not really "on your network". Besides, ICS runs on only a fraction of Android devices.
Rather than an active netscan approach, you're left with a passive monitoring approach. If your network is secure, sniffing the encrypted packet is possible, but inconvenient. You'll have to
put your network interface into monitor mode
capture the 4-way handshake
decrypt it using the network's pre-shared key
this will give you the key you need to decrypt traffic
If you want to see this in action, Wireshark supports WPA decryption.
Once you're able to view the Wi-Fi traffic, you will notice Android devices tend to communicate with certain Google servers and their HTTP connections have User Agent strings that can be identified.
This is the basis for a workable passive solution.
Tenable Network Security offer products that seem to take this type of approach.
Another Idea
#Michelle Cannon mentioned Libelium's Meshlium Xtreme whose approach will not get you all the way there (not without good up to date MAC address range tables). But it could be part of reaching a lesser goal.
You can:
Detect all wireless devices
Eliminate Apple devices using the MAC's Organizationally Unique Identifier (OUI)
Tell it's a mobile device by by monitoring signal strength to determine it's moving (and mobile devices will tend to show up and go away)
You may be able to use the MAC OUI as a hint it's Android
You may be able to use the MAC OUI as a hint it's not Android (but a laptop or wireless card, etc.).
This may be workable if your willing to detect devices that are probably Android.
DHCP Fingerprinting
#Michelle Cannon suggested DHCP fingerprinting. I wasn't sure at first but I have to thank him for suggesting what's looking like the best bet for simple passive scanning. As a cautionary tail, I'd like to explain why I was late to the party.
There are things we know, thinks we don't know, and things we think we know but are wrong.
In a lot of ways, it's good that Android uses the Linux kernel. But it's not good if you want to discover Android devices on your network. Android's TCP/IP stack is Linux's therefor Android devices will look like Linux devices or so I thought at first. But then I realized Linux has a lot of build configuration parameters so there could be something distinctive about Android when seen on a network, but what?
DHCP fingerprinting uses a the exact DHCP options requested by the device plus timing. For this to work you generally need an up to date fingerprint database to match against. At first it looked like fingerbank was crowed sourcing this data, but then I noticed their files hadn't been updated for almost a year. With all the different Android device types, I don't think it's practical to keep updated fingerprints for a single project.
But then I looked at the actual DHCP signatures for Android and I noticed this:
Android 1.0: dhcpvendorcode=dhcpcd 4.0.0-beta9
Android 1.5-2.1: dhcpvendorcode=dhcpcd 4.0.1
Android 2.2: dhcpvendorcode=dhcpcd 4.0.15
Android 3.0: dhcpvendorcode=dhcpcd-5.2.10
Linux normally uses dhclient as their DHCP client, but Android is using dhcpcd. Android has a strong preference for using software licensed with the BSD style where possible and dhcpcd uses a BSD license. It would seem dhcpvendorcode could be used as a strong indicator that a mobile device is running Android.
DHCP monitoring
A client uses DHCP to get an IP address when joining a network so it's starting without an IP address. It gets around this problem by using UDP broadcasts for the initial exchange. On Wi-Fi, even with WPA, broadcast traffic is not encrypted. So you can just listen on UDP port 67 for client to server traffic and 68 for the reverse. You don't even need to put your network interface into promiscuous mode. You can easily monitor this traffic using a protocol analyzer like Wireshark.
I preferred to write code to monitor the traffic and decided to use Python. I selected pydhcplib to handle the details of DHCP. My experience with this library was not smooth. I needed to manually download and place IN.py and TYPES.py support files. And their packet to string conversion was leaving the dhcpvendorcode blank. It did parse the DHCP packets correctly, so I just wrote my own print code.
Here's code that monitors DHCP traffic from client to server:
#!/usr/bin/python
from pydhcplib.dhcp_packet import *
from pydhcplib.dhcp_network import *
from pydhcplib.dhcp_constants import *
netopt = {
'client_listen_port':"68",
'server_listen_port':"67",
'listen_address':"0.0.0.0"
}
class Server(DhcpServer):
def __init__(self, options):
DhcpServer.__init__(
self,options["listen_address"],
options["client_listen_port"],
options["server_listen_port"])
def PrintOptions(self, packet, options=['vendor_class', 'host_name', 'chaddr']):
# uncomment next line to print full details
# print packet.str()
for option in options:
# chaddr is not really and option, it's in the fixed header
if option == 'chaddr':
begin = DhcpFields[option][0]
end = begin+6
opdata = packet.packet_data[begin:end]
hex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
print option+':', ':'.join([(hex[i/16]+hex[i%16]) for i in opdata])
else:
opdata = packet.options_data.get(option)
if opdata:
print option+':', ''.join([chr(i) for i in opdata if i != 0])
print
def HandleDhcpDiscover(self, packet):
print "DHCP DISCOVER"
self.PrintOptions(packet)
def HandleDhcpRequest(self, packet):
print "DHCP REQUEST"
self.PrintOptions(packet)
## def HandleDhcpDecline(self, packet):
## self.PrintOptions(packet)
## def HandleDhcpRelease(self, packet):
## self.PrintOptions(packet)
## def HandleDhcpInform(self, packet):
## self.PrintOptions(packet)
server = Server(netopt)
while True :
server.GetNextDhcpPacket()
This code is based on pydhcplib's server example because it listens for client requests, like a server.
When my Nexus 7 Android 4.2 tablet connects, this interesting information is captured (redacted):
DHCP REQUEST
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff
DHCP DISCOVER
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff
The host name seems to have a fixed format and is easily parsed. If you need the IP address you can monitor the server to client traffic. Note: only the initial exchange, when an new client first shows up without an IP address, is broadcast. Future lease extensions, etc., are not broadcast.
Reverse DNS Lookup
#Luis posted a great solution that demonstrates how simpler is better. Even after seeing Android's DHCP client was setting host_name to android-5c1b97cdffffffff, I didn't think to ask the router for it's list of names using reverse DNS lookups. The router adds the host_name to it's DNS server so you can still access the device if its IP address changes.
The host_name is expected to remain listed in the DNS for the duration of the DHCP lease. You could check if the device is still present by pinging it.
One drawback to depending on host_name is there are ways this could be changed. It's easy for the device manufacturer or carrier to change the host_name (though after searching, I've been unable to find any evidence they ever have). There are apps to change host name, but they require root so that's, at most, an edge case.
Finally there's an open Android Issue 6111: Allow a hostname to be specified that currently has 629 stars. It would not be surprising to see configurable host_name in Android Settings at some point in the future, maybe soon. So if you start depending on host_name to identify Android devices, realize it could be yanked out from under you.
If you're doing live tracking, another potential problem with Reverse DNS Lookup is you have to decide how frequently to scan. (Of course this is not an issue if you're just taking a one-time snapshot.) Frequent scanning consumes network resources, infrequent leaves you with stale data. Here's how adding DHCP monitoring can help:
On startup use Reverse DNS Lookup to find devices
Ping devices to see if they are still active
Monitor DHCP traffic to detect new devices instantly
Occasionally rerun DNS Lookup to find devices you might have missed
If you need to notice devices leaving, ping devices at desired timing resolution
While it's not easy (nor 100% accurate), there are several techniques that make it possible to discover Android devices on your network.
AFAIK, Android system doesn't provide any zeroconf app/service on it's built-in system app/service stack. To enable the auto-discovery on the actual device attached to local network, you need either install some third-party zeroconf app or develop your own app/service and install it on the actual device, some API options are:
JmDNS (for Apple's bonjour protocol)
Cling (for Microsoft's UPnP protocol)
Android NSD API (introduced since Android 4.1)
I am not quite clear about your requirements, if you want something similar (i.e. auto discover and connect) on vanilla Android devices, you can probably use Wi-Fi direct which is now available on some later device running Android 4.0, however, it requires both devices support Wi-Fi Direct and only create an ad-hoc P2P connection with Wi-Fi turned off, much like a bluetooth connection with a longer range:
For Wi-Fi Direct API support, check out official guide - Connecting Devices Wirelessly.
I am looking at this an thinking
http://www.libelium.com/smartphones_iphone_android_detection
pay special note to this
Do the users need to have an specific app installed or interact somehow to be detected?
No, the scan is performed silently, Meshlium just detects the "beacon frames" originated by the Wifi and Bluetooth radios integrated in the Smartphones. Users just need to have at least one of the two wireless interfaces turned on.
Long time ago I use to use an app called stumbler on my mac to find wifi networks, I think this is similar
Other ideas
Well if I need to determine android phones on a local network how would I do it. Absent of a dns service running I only have a couple possibilities
The SSID if its being broadcast - can't tell me anything The ip address - android lets you have a lot of control over host naming so I guess you could define a specific ip range to your android devices. -not to useful.
Alternately lets say I see an unknown device on the network, if bluetooth is turned on then I am broadcasting a bluetooth device signature SDPP that I can use to deduce my device type.
If I were running a service that supported android and I wanted to discover specific android devices on my network, then I could just register the mac addresses for those devices and watch for them on the network.
Other than that you would need to run either a bonjour (dns-sd) or upnpp dameon on the device.
Updated Response
Sorry, I haven't understood the original question correctly. Only your comment made it really clear to me that you do not want to have to install anything on the target devices but you just want a way of discovering random phones in your network.
I'm not sure if this would really be possible in the way you want it. Without having any network discovery service running on Android you will not find the device in first place. Of course you can use some low-level network protocols but that would only give you an indicator that there's something but not what it is (being an Android device, a PC, a whatever else).
The most promising approach would be to check for preinstalled apps that have network functionality of some kind. E.g. Samsung devices have Kies Air (if the user enables it), Motorola are using UPnP for their Media Server and HTC has something own as well, if I remember correctly. However, there's no app that is installed on all Android devices of all vendors and carriers. So you can't rely on solely one of those but would need to check for various different services using their specific protocols and behaviors in order to get additional information about the device. And, of course, the user would have to enable the functionality in order for you to use it.
Old response
An additional alternative to yorkw's list is AllJoyn by Qualcomm. It's an open source cross-platform discovery and peer-to-peer communication framework I've used in the past myself already.
Though Qualcomm is a big sponsor of AllJoyn this does not mean that you need a Qualcomm chipset in your define. In fact AllJoyn works on any chipset including Intel and nVidia. It doesn't require rooted phones or any other modifications to the Android framework and just works "out of the box" using Wi-Fi and/or Bluetooth as pairing methods.
I am learning a lot from this topic.
there is also something called dhcp fingerprinting, apparently different devices act differently to the kind of network scans we've been discussing such as those using NMAP a linux scanner. Maps of the behavior from these probes are available on the internet.
http://www.enterasys.com/company/literature/device-profiling-sab.pdf
https://media.defcon.org/dc-19/presentations/Bilodeau/DEFCON-19-Bilodeau-FingerBank.pdf
http://community.arubanetworks.com/t5/ArubaOS-and-Mobility-Controllers/COTD-DHCP-Fingerprinting-how-to-ArubaOS-6-0-1-0-and-above/td-p/11164
http://myweb.cableone.net/xnih/
Here's a one liner that pings all of the machines on your network (assuming your network is 192.168.1.x) and does a reverse lookup on their names:
for i in {1..255}; do echo ping -t 4 192.168.1.${i} ; done | parallel -j 0 --no-notice 2> /dev/null | awk '/ttl/ { print $4 }' | sort | uniq | sed 's/://' | xargs -n 1 host
Requires GNU parallel to work. You can install that on OSX using "brew install parallel"
From this you can just look at the devices named android-c40a2b8027d663dd.home. or whatever.
You can then trying running nmap -O on a device to see what else you can figure out:
sudo nmap -O android-297e7f9fccaa5b5f.home.
But it's not really that fruitful.

How does Modem code talk to Android code

I would like to know high level idea of how Android Modem code will call/pass message to Android application layer. Say we take SMS for example. If network sends SMS and Modem (say Qualcomm C code parses it) how is it transmitted to Android Application layer?
Is there always a JNI call happening? as interface between modem and Android? Can you please share the information with us. Thanks
In almost all android source base as found in the AOSP/CAF/CM source (Android Open Source Project, CodeAurora Forum, Cyanogenmod respectively), will have C code called the rild, (Radio Interface Layer Daemon). This is commonly found within the /hardware/ril of the source tree.
This daemon runs from the moment Android boots up, and creates a socket called /dev/socket/rild and /dev/socket/rild-debug. There will be a proprietary library coming from Qualcomm, HTC, that gets dynamically loaded at run time upon boot. It is that proprietary library that in turn, communicates to the radio firmware. And the rild's hooks for the call-backs into the proprietary library is established there and then.
At the rild layer, via the aforementioned socket, is how the Android layer (found in the source tree, frameworks/base/telephony/com/android/internal/telephony/RIL.java) communicates.
On the Java side, it opens the socket for reading/writing, along with establishing intents and setting up delegates for broadcasting/receiving events via this socket.
For example, an incoming call, the proprietary library, invokes a callback hook as set up by rild. The rild writes standard generic AT Hayes modem commands to the socket, on the Java side, it reads and interprets the modem commands, and from there, the PhoneManager broadcasts CALL_STATE_RINGING, in which Phone application (found in the source packages/apps/Phone) has registered a receiver and kickstarts the User interface, and that is how you get to answer the call.
Another example, making an outgoing call, you dial a number on Android, the intent gets created and which in turn the PhoneManager (This is the root of it all, here, cannot remember top of my head, think its in frameworks/base/core/java somewhere in the source tree) receives the intent, convert it into either a sequence of AT Hayes modem commands, write it out to the socket, the rild then invokes a callback to the proprietary library, the proprietary library in turn delegates to the radio firmware.
Final example, sending text messages, from the Messaging (found in packages/apps/Mms source tree) application, the text you type, gets shoved into an intent, the PhoneManager receives the intent, converts the text into GSM-encoded using 7-bit GSM letters (IIRC), gets written out to the socket, the rild in turn invokes a callback to the proprietary library, the proprietary library in turn delegates to the radio firmware and the text has now left the domain of the handset and is in the airwaves somewhere... :) Along with sending a broadcast message within Android itself, provided that READ_PHONE_STATE permission is used and specified in the AndroidManifest.xml.
Likewise conversely, when receiving a text message, it is in the reverse, radio firmware receives some bytes, the proprietary library invokes the callback to the rild, and thus writes out the bytes to the socket. On the Java side, it reads from it, and decodes the sequence of bytes, converts it to text as we know of, fires a broadcast with a message received notification. The Messaging application in turn, has registered receivers for the said broadcast, and sends an intent to the notification bar to say something like "New message received from +xxxxxx"
The intents are found in frameworks/base/telephony/java/com/android/internal/telephony/TelephonyIntents.java
That is the gist of how the telephony system works, the real beauty is, that it uses generic AT Hayes modem commands thusly simplifying and hiding the real proprietary mechanisms.
As for the likes of Qualcomm, HTC, forget about it in thinking they'd ever open source the library in question because the radio telephony layer is embedded within the S-o-C (System on a Chip) circuitry!
Which is also, as a side note, why its risky to flash radio firmware, some handsets provide the capability to do it, flash the wrong firmware (such as an incompatible or not suitable for handset), kiss the handset good-bye and use that as a door stopper or paper-weight! :)
It should be noted, that there is zero JNI mechanisms involved.
This is from my understanding of how it works, from what I can tell is this, the radio firmware is loaded into a memory address somewhere where the linux kernel has reserved the address space and does not touch it, something like back in the old PC days when DOS booted up, there was reserved addresses used by the BIOS, I think, its similar here, the addresses marked as reserved are occupied by the firmware, in which the proprietary radio library talks to it - and since the library is running in the address space owned by the kernel, a lá owned by root with root privileges, it can "talk" to it, if you think of using the old BASIC dialect of peek and poke, I'd guess you would not be far off the mark there, by writing a certain sequence of bytes to that address, the radio firmware acts on it, almost like having a interrupt vector table... this am guessing here how it works exactly. :)
Continuing from the explanation by t0mm13b, When we talk about a smartphone, think of 3 layer operations wrt to SMS/Calls.
RIL (User level) <-> AP <-> CP
AP : Application Processor(Where your Android OS runs. Think of games, songs, videos, camera etc running on this processor)
CP : Cellular Processor (Which actually deals with Air-interface for incoming/outgoing calls/sms, interacts with Network Tower etc ..)
Now let say some data is received at CP side (It could be internet data/sms/call). Now there are certain logical channels between AP and CP. So CP will push the data received to a corresponding channel based on type of data. This data will be received by AP. AP will send this data back to RIL/App. RIL will decode this data (specially call/sms data). Based on that gives notification to User about SMS/Call.

Categories

Resources