Some API changes on iOS 10

Posted by Rogerio |01 Sep 16 | 0 comments

Some API changes on iOS 10

I’ve been trying the iOS 10 betas (currently testing the build 14A5346a) on one of my devices, an iPhone 5S 64GB. As an user, I’m loving it: I haven’t experienced any major bugs, and the interface is very pleasing to me – the animations are more fluid and more present in many UI actions.

However, as a developer, it’s one the most annoying releases Apple ever made. Probably claiming that the measure is to protect user’s privacy, Apple disabled some APIs used to get important information about the hardware, battery and open connections of the device. And this is not the first time! Let’s use our TimeMachine, go back in time, and see what Apple have been removing in the past years:

 

  1. System Log on ASL – Apple System Log;
  2. Process List on sysctl;
  3. Device UDID;
  4. Netstat;
  5. Battery Cycles, Health State, Real Max Charge, etc;
  6. MAC Address, etc…

 

 

1. Apple System Log facility

ASL was a feature that allowed apps to access the device’s system log. Like the Console App on macOS, this API allowed search on this database, and was used in the first releases of Lirum Device Info.

LirumLogs

This was the return (running on an iPad 2, on iOS 6).

However, in 2013, Apple stripped iOS 7 of this feature, and after this version, ASL only returned logs generated by the same app reading the logs. In this case, I really think Apple was right in blocking this access, because some sensitive information were printed in those logs – any NSLog entry would potentially be there, in plain text, including calls to URLs, keys, printed exceptions, etc. Anyway, we had to remove the feature in an update (as it would be awkward to have a panel just for our own logs entries in an app that claims to be a system diagnostics tool).

 

 

 

2. Sysctl – Process List

sysctl is a native command on Unix-like operating systems, that queries system calls for some internal OS/hardware informations. As iOS is a descendant of Unix, it contains the libraries required to query sysctl these data.

Apple iOS Developer Library states that the KERN_PROC parameter returns the entire process table – or a subset of it. Back then, it used to return all processes.

 

LirumProcesses

In WWDC 2015, Session 703 (Privacy and Your App), Apple revealed that sysctl would not list processes anymore – again, due to privacy concerns.

In iOS 9, the sandbox now prevents a process from accessing the kern.proc, kern.procargs, and kern.procargs2 values for other processes

So, again, we had to remove another panel from our app.

 

 

 

 

3. Device UDID

UDID is an unique identifier for each iOS device, simple as that. Every app running on a given iPhone or iPad could see this long hexadecimal number by calling

As the ID was the same for every App installed, any query made on Google Chrome for instance, could be linked to the device that originated it, and Google could sell this information for advertisers of other companies, other App providers, etc. The click on an Ad could be directly linked to the install of an App from another vendor, and so forth.

In May 1st, 2013, Apple released a statement:

Starting May 1, the App Store will no longer accept new apps or app updates that access UDIDs. Please update your apps and servers to associate users with the Vendor or Advertising identifiers introduced in iOS 6

Instead of using the UDID (that is one and only for every App installed on the same device), Apple suggests to  replace it with identifierForVendor, which, as the name implies, is the same only for Apps of the same developer.

The UDID still exists, and you can check yours following our guide in here, using Apple’s own iTunes. The information just can’t be retrieved programmatically anymore.

If you still need to identify a device, you can use the following snippet below:

Beware however, that after the user uninstalls your App and installs it again, the identifierForVendor will change (and obviously the userDefaults will be cleared as well). If you need to persist the ID between uninstalls, you can store it in the keychain – to make that easier, I personally use SAMKeychain.

After adding SAMKeychain cocoapod, you can just use it:

But, for a diagnostics application, showing an ID unique to Lirum would be pointless. So, again, we had to remove the feature in an update to Lirum Device Info.

 

 

4. Netstat

Oh, netstat… The simple prospect of losing this feature hurts my heart. It was a real challenge to implement it. But first: netstat is a command line tool that works natively in macOS, Linux, BSD and even Windows. It returns all network connections, routing tables, and other statistics of the network interfaces and protocols. To check it out, type

on your macOS Terminal, or Windows Command Prompt. The return must be something like this:

Netstat-Mac

For iOS devices, there isn’t a built-in tool for that, so we adapted the netstat open source code to provide this information. But, for that to work, we had to adapt and redeclare a number of Unix .h files, some available from opensource.apple.com, some from Linux sources, and some from BSD. Then, we had to strip away portions of code that would not run, portions that returned exceptions, or just were not applicable. In the end, the library returned what we needed and we used it in our App since version 2.0 (I think), released in 2013.

RIP Connections Panel – 2013-2016

Well, the code still works on iOS versions prior to iOS 10 (it does not work on all the betas), so we released the library as an open source, with a very simplified UI. It is available on my github at:

https://github.com/rogerioth/Lirum.Network

In this case I will probably make the panel in Lirum Info available as a ‘deprecated’ tool, and come up with a message in case the user is running it on iOS 10.

 

5. Battery Cycles and Health State

IOKit. This beautiful framework collection, is a wonder for us geeks: it provides provided a plethora of very interesting hardware information. According to Apple, “the I/O Kit is a collection of system frameworks, libraries, tools, and other resources for creating device drivers in OS X. It is based on an object-oriented programming model implemented in a restricted form of C++ that omits features unsuitable for use within a multithreaded kernel.”

It is considered a ‘private framework’, meaning that Apple won’t usually allow Apps that use it to be approved on the App Store. It’s even hard now to link the IOKit.framework within XCode, and even harder to use it’s .h files. And even if you succeed in doing so, the automated submission process will immediately reject your binary. There was someone that made a good solution to bypass such process: Cristopher Lyon Anderson from Electric Labs made an open source app called IOKit Browser. Basically, it replicated some of the typedefs declared inside IOKit .h files (so, we would not have to use them), and made the reference to the IOKit from the inside, specifying the bundle path and getting function pointers:

After that, he made a very handy navigation tool, that browses through the nodes, returning the information hierarchy in a way that reminded me of WMI (Windows Management Instrumentation). The node path for the battery data is: Root/Model/AppleARMPE/charger/AppleARMPMUCharger

The App running on iOS 9.3.5 (iPhone 6S Plus):

IMG_5163

And now, the same App running on iOS 10 Beta (14A5346a on an iPhone 5S)

IMG_0043

Only the basic information remains: no ‘AppleRawMaxCapacity’ (that was the real max capacity of the battery), no ‘CycleCount’ (that was the number of battery cycles), and a lot of other battery data are missing. Can Apple argue that this removal is intended to protect the privacy of the customers? For me it just seems to be a maneuver to block Apps that shows the real state of the device’s battery, like Lirum Info itself, Battery Life from Robert Tkotzyk or Battery Percentage from Hien Mai, all of which stopped returning the number of battery cycles after iOS 10. Perhaps letting the user know the state of the battery may either make more users go to Apple Stores seeking replacement of the component, or the information itself may damage the image of Apple as a company that chooses the best parts for its products: what if the battery in one specific case is refurbished, and it shows on these Apps? What a PR damage would it make, right? So, let’s just block these sensitive information that developers should never had access to begin with! Why don’t just block the real sensitive data, like IMEI, MAC Address, etc? (these are not accessible from IOKit anymore either, but I can totally agree with their removal).

 

Lirum Info with a Healthy Battery:

 

Lirum Info with an Unhealthy Battery:

So, we lost another panel in our App… T.T

 

In one hand I’m happy to see that Apple does take user privacy very seriously – most of these informations can be used by malware to either identify the device or the user, and even gather intel about the user behaviour: the Apps installed, URLs called, etc. However, mixing battery health state with these and pretending that this blocking is intended to protect the user is something a bit fishy IMHO. Users have the right to know the wear state of any component inside the machine they brought. That won’t matter anyway: September, 7th 2016, Apple will probably be releasing the final iOS 10 to the public, after revealing the next iPhone, and these APIs will be lost.

 

 


Leave a Reply

Be the First to Comment!

Notify of
avatar
wpDiscuz