-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathatom.xml
More file actions
925 lines (655 loc) · 95.1 KB
/
atom.xml
File metadata and controls
925 lines (655 loc) · 95.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Christopher Lyon Anderson]]></title>
<link href="http://www.lyonanderson.org/atom.xml" rel="self"/>
<link href="http://www.lyonanderson.org/"/>
<updated>2014-11-13T11:49:20+00:00</updated>
<id>http://www.lyonanderson.org/</id>
<author>
<name><![CDATA[Christopher Lyon Anderson]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[iOS Diagnostics (Part 3)]]></title>
<link href="http://www.lyonanderson.org/blog/2014/11/13/ios-diagnostics-part-3/"/>
<updated>2014-11-13T11:33:00+00:00</updated>
<id>http://www.lyonanderson.org/blog/2014/11/13/ios-diagnostics-part-3</id>
<content type="html"><![CDATA[<p>Following up from my last <a href="http://www.lyonanderson.org/blog/2014/11/05/ios-diagnostics-part-2/">post</a> on analysing iOS diagnostics I decided to see if it was possible to get the logs without having to go through a proxy and the built in diagnostics app. A quick look using <a href="http://www.hopperapp.com/">Hopper</a> revealed that the built in diagnostics app uses a framework called <code>iOSDiagnosticsSupport.framework</code> to do the heavy lifting.</p>
<p>Armed with this info I built a quick app to do on device diagnostics. I’ve covered most of the sections found in the report you could generate using the techniques I outlined in the last post. There are many more things I want to add, but this is a start. The project is on github <a href="https://github.com/lyonanderson/iOS-Diagnostics">here</a>. It needs more work - especially on the iPad. I’ll be improving and adding more sections in the coming weeks and months. I’ve already found it useful in seeing more clearly what’s chewing up the battery on my iPad and iPhone. You can export your logs from the app using the share button.</p>
<p><img src="https://raw.githubusercontent.com/lyonanderson/iOS-Diagnostics/master/screenshots/Screenshot1.png" alt="Screenshot" /></p>
<p><img src="https://raw.githubusercontent.com/lyonanderson/iOS-Diagnostics/master/screenshots/Screenshot2.png" alt="Screenshot" /></p>
<p><img src="https://raw.githubusercontent.com/lyonanderson/iOS-Diagnostics/master/screenshots/Screenshot3.png" alt="Screenshot" /></p>
<div class="embed-video-container"><iframe src="http://www.lyonanderson.org//player.vimeo.com/video/111691295 "></iframe></div>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[iOS Diagnostics (Part 2)]]></title>
<link href="http://www.lyonanderson.org/blog/2014/11/05/ios-diagnostics-part-2/"/>
<updated>2014-11-05T17:44:00+00:00</updated>
<id>http://www.lyonanderson.org/blog/2014/11/05/ios-diagnostics-part-2</id>
<content type="html"><![CDATA[<p>Last year I <a href="http://www.lyonanderson.org/blog/2014/02/06/ios-power-diagnostics/">blogged</a> about getting detailed diagnostics from iOS using a proxy. With iOS 8, Apple has significantly improved the detail contained in the diagnostic dump. Gone is the text file and in comes a sqlite database containing about 100 tables. This will make analysing the data much easier. Furthermore, the tables give us a clearer indication of what data might be available. We’re going to use SQL to extract and process the data and see what we can tell. So head over to <a href="http://www.lyonanderson.org/blog/2014/02/06/ios-power-diagnostics/">here</a> and get your data.</p>
<p>I’ve tried to detail some of the things I’ve found below. However, my real motive was to provide a way of finding out what was using draining the battery on my iOS devices. We’ve all had the scenario where we’ve not really used our devices but the battery has mysteriously run down. To this end I put together a quick python hack that generates a report from your diagnostic database. You can find the tool <a href="https://github.com/lyonanderson/powerAnalysis">here</a>. I plan to add more sections in the coming months. You can find an example report <a href="http://lyonanderson.org/report.html">here</a> taken from my iPhone . In the time period shown the battery had been draining, but I had not been using it. The report shows that I was getting lots of push notifications concerned with the key value store. If I connect my iPhone to the Charles Proxy I can see it’s constantly posting to keyvalueservice.icloud.com. Presumably in response to a push notification telling it something has changed.</p>
<h2>Battery Drain</h2>
<p>There are two tables, <code>PLBatteryAgent_EventBackward_Battery</code>, <code>PLBatteryAgent_EventBackward_BatteryUI</code>, populated with detailed battery information. Table <code>PLBatteryAgent_EventBackward_Battery</code> contains the most detail including voltage, battery level, current, cycle count. For 5 days I have nearly 11,000 rows!</p>
<p>We can extract time and level using the following SQL:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT datetime(timestamp, 'unixepoch'), Level from PLBatteryAgent_EventBackward_Battery</span></code></pre></td></tr></table></div></figure>
<p>We can use this to make a nice graph of how batter level changes over time:</p>
<p><img src="http://www.lyonanderson.org/images/batteryLevels.png" alt="Graph" /></p>
<h2>Energy </h2>
<p>There is wealth of energy diagnostic information kept by iOS. The table <code>PLIOReportAgent_EventBackward_EnergyModel</code> seems to take a snapshot of power usage broken down by CPU, DRAM, GPU, SoC Energy. Much more interesting is the table <code>PLBLMAccountingService_Aggregate_BLMAppEnergyBreakdown</code> which contains, on a per app basis, where the energy is being used. It’s broken down into fields such as: Airdrop, AirplayMirroring , BLMEnergyDisplay, BLMEnergyGPS, BLMEnergyGPU, BLMEnergyPA_accessories, BLMEnergyPA_apsd, BLMEnergyWiFi, BLMEnergyTorch. Samples appear to be on an hourly and daily basis. I would imagine this table is used to populate the energy breakdown you can get in the Settings.app. This really is a treasure trove! For example, you can tell which apps used location in the background. The times are on hour boundaries:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT datetime(timestamp, 'unixepoch') AS TIME, BLMAppName FROM PLBLMAccountingService_Aggregate_BLMAppEnergyBreakdown WHERE BLMEnergy_BackgroundLocation > 0 ORDER BY TIME</span></code></pre></td></tr></table></div></figure>
<p>These tables are a good place to see which apps and internal processes are using power. Note that some of the columns always seem to be 0. You can see overall energy per app per day:</p>
<p>SELECT datetime(timestamp, ‘unixepoch’) AS TIME, BLMAppName, BLMEnergy FROM PLBLMAccountingService_Aggregate_BLMAppEnergyBreakdown WHERE
timeInterval=’3600’
ORDER BY TIME</p>
<p>When the device was sleeping and awake:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT datetime(timestamp, 'unixepoch') AS Time, * FROM PLSleepWakeAgent_EventForward_PowerState</span></code></pre></td></tr></table></div></figure>
<h2>Audio</h2>
<p>The are several tables concerned with audio: <code>PLAudioAgent_EventPoint_AudioApp</code>, <code>PLAudioAgent_EventForward_Output</code>, <code>PLAudioAgent_EventForward_Routing</code>, <code>PLAudioAgent_EventPoint_AudioApp</code>. The following SQL shows you when you had headphones connected and broadly what kind of audio was coming out (Audio/Video, Call, Ringtone etc)</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT datetime(timestamp, 'unixepoch') AS TIME, OutputCategory FROM PLAudioAgent_EventForward_Routing WHERE HeadphonesConnected</span></code></pre></td></tr></table></div></figure>
<h2>Camera</h2>
<p>There are three tables concerned with the camera: <code>PLCameraAgent_EventForward_BackCamera</code>, <code>PLCameraAgent_EventForward_FrontCamera</code>, and <code>PLCameraAgent_EventForward_Torch</code> The following SQL will show you when the back camera was on:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT datetime(timestamp, 'unixepoch') AS TIME FROM PLCameraAgent_EventForward_BackCamera WHERE State = 1</span></code></pre></td></tr></table></div></figure>
<p>You can do a similar thing for the front camera and the torch/flash.</p>
<h2>Core Location</h2>
<p>iOS keeps track of which apps ask for location and how long they use it for, and the desired accuracy. <em>Note the actual location is not recorded!</em> The following SQL will show you the total number of location requests per client.</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT Client, COUNT(Client) AS Count FROM PLLocationAgent_EventForward_ClientStatus GROUP BY Client ORDER BY Count DESC</span></code></pre></td></tr></table></div></figure>
<p>The biggest user for me was <code>com.apple.locationd.bundle-/System/Library/LocationBundles/Routine.bundle</code> which belongs to the process <code>routined</code>. I think <code>routined</code> is the frequent locations service i.e. the one that tells you in notification centre how long it will take to get home. You can see what’s being stored by looking in frequent locations in Settings -> Privacy -> Location -> System -> Frequent Locations.</p>
<h2>Push Notifications</h2>
<p>It would appear iOS logs when each push notification arrives. This includes the silent background ones too. It includes which push server you were connected to, and whether you were on Wifi on Cellular. There appears to be a priority fields, but I’m not sure what that’s used for. The following SQL will show you the total number of push notifications per app/service (Apple refers to these as topics)</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT Topic, COUNT(Topic) AS Count FROM PLXPCAgent_EventPoint_Apsd GROUP BY Topic ORDER BY Count DESC</span></code></pre></td></tr></table></div></figure>
<p>My biggest hitter was <code>com.me.keyvalueservice</code> followed by <code>com.apple.madrid</code>. You can break down the data in terms of the number of push notifications in a given period. To see number of push notifications on an hourly basis:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT T, COUNT(T) AS Count FROM (SELECT strftime('%Y-%m-%d %H:00', datetime(timestamp, 'unixepoch')) as T FROM PLXPCAgent_EventPoint_Apsd) GROUP BY T</span></code></pre></td></tr></table></div></figure>
<h2>Application Usage</h2>
<p>See when apps are doing some background processing:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT datetime(timestamp, 'unixepoch') AS Time, Identifier, DisplayName from PLApplicationAgent_EventNone_ApplicationMetaData, PLApplicationAgent_EventNone_ApplicationMetaData_Array_UIBackgroundModes
</span><span class='line'>where PLApplicationAgent_EventNone_ApplicationMetaData_Array_UIBackgroundModes.fk_id = PLApplicationAgent_EventNone_ApplicationMetaData.id GROUP BY Time, Identifier</span></code></pre></td></tr></table></div></figure>
<p>See how many times each application has performed different kinds of background activity (e.g. location, audio, fetch etc):</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT identifier, value, count(value) as Count from PLApplicationAgent_EventPoint_Application, PLApplicationAgent_EventNone_ApplicationMetaData_Array_UIBackgroundModes
</span><span class='line'>where PLApplicationAgent_EventNone_ApplicationMetaData_Array_UIBackgroundModes.fk_id = PLApplicationAgent_EventPoint_Application.id
</span><span class='line'>group by Identifier, value</span></code></pre></td></tr></table></div></figure>
<p>iOS appears to sample how much processing time each process gets. The sample length seems vary from sample to sample:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT value, processname, datetime(timestamp, 'unixepoch') AS Start, datetime(timestampEnd, 'unixepoch') AS End FROM PLProcessMonitorAgent_EventInterval_ProcessMonitorInterval_Dynamic, PLProcessMonitorAgent_EventInterval_ProcessMonitorInterval WHERE PLProcessMonitorAgent_EventInterval_ProcessMonitorInterval.ID = PLProcessMonitorAgent_EventInterval_ProcessMonitorInterval_Dynamic.FK_ID
</span><span class='line'>GROUP BY timestamp, timestampEnd,processname</span></code></pre></td></tr></table></div></figure>
<p>or see the total processing time for each process:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT SUM(value) AS TotalTime, processname FROM PLProcessMonitorAgent_EventInterval_ProcessMonitorInterval_Dynamic, PLProcessMonitorAgent_EventInterval_ProcessMonitorInterval WHERE PLProcessMonitorAgent_EventInterval_ProcessMonitorInterval.ID = PLProcessMonitorAgent_EventInterval_ProcessMonitorInterval_Dynamic.FK_ID
</span><span class='line'>GROUP BY processname ORDER BY TotalTime DESC</span></code></pre></td></tr></table></div></figure>
<h2>Radio</h2>
<p>The table <code>PLBBAgent_EventPoint_TelephonyActivity</code> keeps track of how much signal you have (including the number of bars), whether you are in a call, and if you’re on LTE, 3G, 2G and if airplane mode is active. There is another table, <code>PLBBAgent_EventPoint_TelephonyRegistration</code> which details which operator you are connected too.</p>
<p>The following SQL will show you your signal strength at each recorded time point:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT timestamp, signalstrength from PLBBAgent_EventPoint_TelephonyActivity</span></code></pre></td></tr></table></div></figure>
<h2>Display</h2>
<p>The table <code>PLDisplayAgent_EventForward_Display</code> contains detailed recordings of your screen metrics including brightness and how much current is being used. Another table <code>PLDisplayAgent_EventPoint_UserBrightness</code> seems to record when you override the brightness manually.</p>
<h2>Power Assertions</h2>
<p>Find out the different kinds of power assertions:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT AssertType FROM PLPowerAssertionAgent_EventInterval_Assertion GROUP BY AssertType</span></code></pre></td></tr></table></div></figure>
<p>I had the following: <code>AssertionStorm</code>, <code>BackgroundTask</code>, <code>EnableIdleSleep</code>, <code>InternalPreventDisplaySleep</code>, <code>NoIdleSleepAssertion</code>, <code>PreventUserIdleDisplaySleep</code>. <code>PreventUserIdleSystemSleep</code>
, <code>SystemIsActive</code></p>
<p>Find assertions relating to background tasks. The assertion will often contain the name of them method being called:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT datetime(timestamp, 'unixepoch') AS Start, datetime(timestampEnd, 'unixepoch') AS End, timestampEnd - timestamp AS time, * FROM PLPowerAssertionAgent_EventInterval_Assertion WHERE AssertName LIKE '%BKNewProcess%' ORDER BY start</span></code></pre></td></tr></table></div></figure>
<h2>UIKit</h2>
<p>There appears to be some tables concerned with internal UIKit stuff: <code>PLXPCAgent_EventForward_UIKitActivity</code>, <code>PLXPCAgent_EventForward_UIKitAlert</code>, and <code>PLXPCAgent_EventForward_UIKitKeyboard</code>. The table <code>PLXPCAgent_EventForward_UIKitKeyboard</code> appear to show when the keyboard is shown. It also includes which keyboard was used:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>SELECT datetime(timestamp, 'unixepoch') AS TIME, Keyboard-ID FROM PLXPCAgent_EventForward_UIKitKeyboard WHERE Status = 1</span></code></pre></td></tr></table></div></figure>
<h2>Conclusions</h2>
<p>Overall, I think the fact that Apple is collecting these kinds of metrics is a good thing. It will allow them to better understand how customers are using their devices, and thus draining their batteries. I assume that this data is only harvested when you go to the genius bar and they run through the diagnostics app with you. However, I could be wrong and it could be part of the standard Diagnostics and Usage data collections.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[iOS IOKit Browser]]></title>
<link href="http://www.lyonanderson.org/blog/2014/02/12/ios-iokit-browser/"/>
<updated>2014-02-12T09:12:00+00:00</updated>
<id>http://www.lyonanderson.org/blog/2014/02/12/ios-iokit-browser</id>
<content type="html"><![CDATA[<p>On OS X there is a tool called <a href="https://developer.apple.com/library/mac/documentation/darwin/reference/manpages/man8/ioreg.8.html">ioreg</a> that lets you dump out the contents of your I/O Kit registry. On OS X and iOS the I/O Registry contains a wealth of information about the hardware connected to your device. If you want to write device drivers then you’d have to get your hands dirty with IOKit. If you fancy some bedtime reading there is more information <a href="https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/Introduction/Introduction.html#//apple_ref/doc/uid/TP0000011-CH204-TPXREF101">here</a>.</p>
<p>I thought it would be interesting to see what I could get out of IOKit on iOS. Fortunately, Apple provide the source to <a href="http://opensource.apple.com/source/IOKitTools/IOKitTools-89.1.1/ioreg.tproj/ioreg.c">ioreg</a>.
So I made a little iOS app based around it. Of course, IOKit is a private API on iOS and our app will be running inside of the Sandbox. That said, there is a wealth of information available. You can drill down into the I/O Registry tree and you can search too. It’s pretty quick and dirty and looks like this:</p>
<p><img src="http://www.lyonanderson.org/images/IMG_0005.PNG" alt="Screenshot" />
<img src="http://www.lyonanderson.org/images/IMG_0006.PNG" alt="Screenshot" /></p>
<br/>
<p><img src="http://www.lyonanderson.org/images/IMG_0007.PNG" alt="Screenshot" />
<img src="http://www.lyonanderson.org/images/IMG_0008.PNG" alt="Screenshot" /></p>
<p>You can grab the source on <a href="https://github.com/lyonanderson/IOKitBrowser">github</a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[iOS Diagnostics]]></title>
<link href="http://www.lyonanderson.org/blog/2014/02/06/ios-power-diagnostics/"/>
<updated>2014-02-06T21:41:00+00:00</updated>
<id>http://www.lyonanderson.org/blog/2014/02/06/ios-power-diagnostics</id>
<content type="html"><![CDATA[<p><em>Update</em> - There is some new information in <a href="http://www.lyonanderson.org/blog/2014/10/05/ios-diagnostics-part-2/">this</a> post relating to iOS 8. The instructions below for obtaining the data dump are still valid.</p>
<p>I’ve recently been having a play with the iOS Diagnostics tool. It turns out that this tool can provide you with a treasure trove of information about your device. From which accessories you have connected, to extremely detailed power usage information. You can get to it by entering the URL <strong>diags://</strong> into Safari. <!-- more --> You’ll be greeted with a screen asking you for a ticket number:</p>
<p><img src="http://www.lyonanderson.org/images/IMG_9491.PNG" alt="Screenshot" /></p>
<p>Where do you get a ticket number from? You could go to the genius bar, but there is an easier way. We can use a a man-in-the-middle proxy and spoof iOS Diagnostics into thinking it has a valid ticket. I decided to use <a href="http://mitmproxy.org">mitmproxy</a> as it supports https and can be scripted. I’ve made a mitmproxy script that you can use to spoof iOS Diagnostics and capture the payload that would be sent to Apple. So let’s being.</p>
<p>When started iOS Diagnostics makes a request to <a href="https://iosdiags.apple.com/ios/TestConfiguration/1.2">https://iosdiags.apple.com/ios/TestConfiguration/1.2</a> to find out what diagnostics are available for your device. The response is a plist containing a dictionary keyed on device type mapping to an array of diagnostic types. The only value I’ve seen is powerDiagnostics. A quick poke around in the binary seems to confirm this is the only accepted value at the moment. If your device type matches you’ll be offered ‘Extended Tests’. Currently Apple only seems to offer this for iPhones and not iPads. However, I’ve been able to get extended diagnostics from an iPad too. You’ll need to edit XML_OK_RESPONSE to include your device type, if you want the more detailed power logs.</p>
<p>If you now enter a ticket number - the script expects 123456 - and press Extended Tests, iOS Diagnostics will make a request to <a href="https://iosdiags.apple.com/MR3Server/ValidateTicket?ticket_number=123456">https://iosdiags.apple.com/MR3Server/ValidateTicket?ticket_number=123456</a>. If you don’t have a valid ticket Apple will politely respond with a not authorised 401. Our script is going to responsd with a 200 and the same body we used before. It appears as though any positive response is good. Next comes the good stuff. iOS Diagnostics will now perform two uploads. First to <a href="https://iosdiags.apple.com/MR3Server/MR3Post">https://iosdiags.apple.com/MR3Server/MR3Post</a> and then, if you choose extended test, to <a href="https://iosdiags.apple.com/ios/log/extendedUpload">https://iosdiags.apple.com/ios/log/extendedUpload</a>.</p>
<p>To get started download and install <a href="http://mitmproxy.org/">mitmproxy</a> and download the script <a href="https://github.com/lyonanderson/lyonanderson.github.com/blob/master/downloads/capture.py">here</a>. As iOS diagnostics uses https you’ll need to install the mitmproxy CA on your device. You can find instructions <a href="http://mitmproxy.org/doc/ssl.html">here</a>. You can start the command line version of mitmproxy - mitmdump - like so:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>mitmdump -e -s capture.py </span></code></pre></td></tr></table></div></figure>
<p>You’ll then need to set your proxy in the wifi settings on your iOS device to the IP address of your machine running the proxy. The default port is 8080. Once you’re all configured go to Safari and go to <strong>diags://</strong> Enter <strong>123456</strong> as the ticket number and select Extended Tests. After a short time you’ll be left with two tar.gz files containing all the good stuff.</p>
<p>The smaller file starting with ‘general’ contains logs relating to iCloud backups, memory and accessories. The accessory logs are in the iAPEvents directory. You’ll need to load them into Console to view them. It looks like each time a device is connected (even those connected over Bluetooth LE) an entry is written. For example:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>Jan 9 21:35:30 Ishras-iPhone-5S iapd[149] <Warning>: AccessoryInfo = {
</span><span class='line'>Jan 9 21:35:30 Ishras-iPhone-5S iapd[149] <Warning>: IAPAppAccessoryNameKey = Apple Digital AV Adapter;
</span><span class='line'>Jan 9 21:35:30 Ishras-iPhone-5S iapd[149] <Warning>: IAPAppAccessoryManufacturerKey = Apple;
</span><span class='line'>Jan 9 21:35:30 Ishras-iPhone-5S iapd[149] <Warning>: IAPAppAccessoryModelNumberKey = A1438;
</span><span class='line'>Jan 9 21:35:30 Ishras-iPhone-5S iapd[149] <Warning>: IAPAppAccessoryFirmwareRevisionKey = 7.0.0 (11A7451);
</span><span class='line'>Jan 9 21:35:30 Ishras-iPhone-5S iapd[149] <Warning>: IAPAppAccessoryHardwareRevisionKey = 1.0.0;
</span><span class='line'>Jan 9 21:35:30 Ishras-iPhone-5S iapd[149] <Warning>: } // End AccessoryInfo</span></code></pre></td></tr></table></div></figure>
<p>The larger file starting with ‘power’ contains all the power logs. It’s a compressed <a href="http://en.wikipedia.org/wiki/Cpio">CPIO</a> file containing a set of compressed text files. There is one file for each day. I found over two weeks of files on my device. Each file is very detailed and on my iPhone 5s about 16mb a day. If you look inside you’ll see lots of entries, each prefixed with a time and type. Most of if is pretty clear, here are some examples:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>02/01/14 00:00:03 [Display] active=yes; brightness=46.5%; user_brightness=<unknown>; lux=5; als=enabled; mie=off; slider=30480; mNits=142559; uAmps=5028;
</span><span class='line'>02/01/14 00:00:03 [BasebandLoggingConfig] Artemis=null(null); Boot=null(null); CSILog=false(-1); CoreDump=null(null); DIAG=false(256); EURCoreDump=1(); MobileAnalyzer=null(null); Mux=null(null); USBDump=null(null); USBTracerDump=null(null);
</span><span class='line'>02/01/14 00:00:19 [Battery] level=62.67%; voltage=3914 mV; current=-200 mA; current_capacity=925 mAh; raw_max_capacity=1476 mAh; charging_state=Inactive; charging_current=0 mA; battery_temp=32.50 C; adapter_info=0; connected_status=0;
</span><span class='line'>02/01/14 00:02:04 [Telephony] current_rat=Automatic; preferred_rat=Automatic; camped_rat=UMTS; call_status=Inactive; airplane_mode=off; signal=-104 dBm; bars=2;</span></code></pre></td></tr></table></div></figure>
<p>As well as power information there is periodic logging of the process table and network statistics. This includes how much time each process has used and how much cellular and wifi data has been used on a per process level:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>02/01/14 00:03:21 [ProcessMonitor] backboardd(31)=555.90s; kernel_task(0)=240.84s; SpringBoard(16)=142.11s; locationd(60)=96.31s; CommCenter(59)=80.51s; aggregated(70)=56.25s; Tweetbot(391)=51.99s; MobileSafari(399)=51.14s; UserEventAgent(15)=29.76s; mediaserverd(29)=24.99s; assetsd(122)=23.74s; WhatsApp(152)=21.93s; MobileSMS(170)=21.53s; wifid(40)=14.15s; networkd(83)=13.57s; configd(42)=13.09s; imagent(23)=10.84s; kbd(118)=10.60s; securityd(84)=10.30s; syslogd(38)=9.88s; Shazam(238)=9.79s; apsd(87)=9.57s; identityservice(53)=9.18s; DuetLST(97)=5.86s; launchd(1)=5.82s; powerd(54)=5.47s; BTServer(48)=5.36s; MobileMail(120)=5.36s; ReadItLaterPro(162)=5.25s; notifyd(73)=4.60s; dataaccessd(109)=3.71s; IMDPersistenceA(81)=3.52s; librariand(111)=3.30s; ubd(52)=3.30s; mDNSResponder(51)=2.97s; itunesstored(95)=2.91s; iapd(144)=2.76s; MobileSlideShow(294)=2.74s; accountsd(86)=2.45s; FindMyFriends(164)=2.45s; iaptransportd(55)=2.42s; fseventsd(19)=2.33s; PebbleApp(357)=1.43s; geod(112)=1.38s; sharingd(21)=1.26s; biometrickitd(108)=1.26s; Offlinemail(379)=1.20s; netatmo(269)=1.16s; National Rail(314)=1.13s; MobileCal(134)=0.99s; BTLEServer(101)=0.97s; assistantd(71)=0.96s; mobileassetd(99)=0.95s; softwareupdates(121)=0.87s; Preferences(367)=0.87s; keybagd(64)=0.85s; routined(33)=0.85s; wirelessproxd(35)=0.84s; fairplayd.H2(44)=0.78s; itunescloudd(94)=0.71s; mediaremoted(65)=0.68s; installd(17)=0.65s; lockdownd(25)=0.61s; SiriViewService(362)=0.51s; aosnotifyd(22)=0.46s; calaccessd(135)=0.42s; medialibraryd(96)=0.37s; timed(37)=0.34s; softwarebehavio(28)=0.32s; filecoordinatio(124)=0.30s; WirelessCoexMan(80)=0.29s; lsd(77)=0.29s; tccd(110)=0.29s; recentsd(176)=0.29s; AGXCompilerServ(395)=0.28s; nsnetworkd(106)=0.28s; AppleIDAuthAgen(32)=0.21s; xpcd(76)=0.20s; touchsetupd(117)=0.20s; AGXCompilerServ(114)=0.19s; AGXCompilerServ(400)=0.17s; MobileGestaltHe(75)=0.16s; storebookkeeper(92)=0.09s; CloudKeychainPr(128)=0.09s; adid(126)=0.09s; BTAvrcp(147)=0.08s; networkd_privil(85)=0.08s; BlueTool(79)=0.06s; assistant_servi(364)=0.06s; notification_pr(388)=0.05s; CMFSyncAgent(98)=0.04s; sandboxd(72)=0.04s; distnoted(78)=0.04s; vmd(20)=0.04s; com.apple.Mobil(102)=0.03s; EscrowSecurityA(103)=0.03s; xpcd(113)=0.02s; oscard(104)=0.02s; softwareupdated(67)=0.01s;
</span><span class='line'>
</span><span class='line'>02/01/14 00:03:21 [Network Connections Symptoms] procName=timed; bundleName=<unknown>; wifi-in=1216bytes; wifi-out=1216bytes; cell-in=0bytes; cell-out=0bytes; sinceTime=09/25/13 09:35:16;
</span><span class='line'>02/01/14 00:03:21 [Network Connections Symptoms] procName=assetsd; bundleName=<unknown>; wifi-in=2524167bytes; wifi-out=663731bytes; cell-in=4018850bytes; cell-out=1112680bytes; sinceTime=09/26/13 23:35:59;
</span><span class='line'>02/01/14 00:03:21 [Network Connections Symptoms] procName=Flipboard; bundleName=com.flipboard.flipboard-ipad; wifi-in=50671132bytes; wifi-out=1055416bytes; cell-in=23766010bytes; cell-out=529125bytes; sinceTime=10/08/13 16:03:23;</span></code></pre></td></tr></table></div></figure>
<p>You can see when background processes wake up the device:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>02/01/14 00:06:06 [Application] id=com.apple.mobileme.fmf1; pid=164.00; mode=Background Running; reason=backgroundContentFetching; UIBackgroundModes=fetch; display_name=Find Friends; executable=FindMyFriends; version=3.0;</span></code></pre></td></tr></table></div></figure>
<p>and when applications are running in the foreground:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>02/01/14 00:14:21 [Application] id=com.apple.mobilesafari; pid=399.00; mode=Foreground Running; reason=<unknown>; UIBackgroundModes=audio,continuousFallback; display_name=Safari; executable=MobileSafari; version=7.0;</span></code></pre></td></tr></table></div></figure>
<p>It’s all interesting stuff. Hopefully I’ll get some time to write scripts to extract graphs from the logs. So next time you have one of those days where the battery lasts no time, take a look in the logs and you’ll probably be able to find the culprit!</p>
<h2>Update (14/2/14)</h2>
<p>The link to the script is now fixed. Sorry about that.</p>
<p>Remember, you’ll only get Quick Test unless your device is included in XML_OK_RESPONSE. You can get a complete list <a href="http://www.everyi.com/by-identifier/ipod-iphone-ipad-specs-by-model-identifier.html">here</a>.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[(Failing to) Make iOS6 Remote View Controllers]]></title>
<link href="http://www.lyonanderson.org/blog/2012/10/08/failing-to-make-ios6-remote-view-controllers/"/>
<updated>2012-10-08T14:47:00+01:00</updated>
<id>http://www.lyonanderson.org/blog/2012/10/08/failing-to-make-ios6-remote-view-controllers</id>
<content type="html"><![CDATA[<p>I’ve been following with great interest Ole Begemann’s <a href="http://oleb.net/blog/2012/10/remote-view-controllers-in-ios-6/">research</a> into remote view controllers in iOS6. I wanted to look at the problem from the other end. I want to make my own remote view controllers. Clearly, we’ll be using private APIs and therefore, none of this can make it into your apps for the store. I’ll say up front I was not able to get this working, but I’ve found some interesting things out.</p>
<!-- more -->
<p>As you’d expect there are two ends to the problem. At one end a service which exports some stuff, at the other end a client. The client requests a remote view controller, from a service provider, and is given an instance of a _UIRemoteViewController which it can present. It would appear that Apple have wrapped up all the XPC heavy lifting into the _UIRemoteViewController and associated _UIViewService classes.</p>
<p>I think I’ve got the client end working, in as much as I can bring up Apple built in remote controllers using the following technique:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">IBAction</span><span class="p">)</span><span class="nf">openChrisController:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">sender</span> <span class="p">{</span>
</span><span class='line'> <span class="n">Class</span> <span class="n">UIRemoteViewController</span> <span class="o">=</span> <span class="n">NSClassFromString</span><span class="p">(</span><span class="s">@"MFMailComposeRemoteViewController"</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="n">UIRemoteViewController</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="p">[</span><span class="n">UIRemoteViewController</span> <span class="nl">requestViewController:</span><span class="s">@"ComposeServiceRemoteViewController"</span> <span class="nl">fromServiceWithBundleIdentifier:</span><span class="s">@"com.apple.MailCompositionService"</span> <span class="nl">connectionHandler:</span><span class="o">^</span><span class="p">(</span><span class="n">UIViewController</span> <span class="o">*</span><span class="n">remoteViewController</span><span class="p">,</span> <span class="kt">id</span> <span class="n">error</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'> <span class="n">NSLog</span><span class="p">(</span><span class="s">@"Arg 1 %@, Arg 2 %@"</span><span class="p">,</span> <span class="n">remoteViewController</span><span class="p">,</span> <span class="n">error</span><span class="p">);</span>
</span><span class='line'> <span class="p">[</span><span class="n">self</span> <span class="nl">presentViewController:</span><span class="n">remoteViewController</span> <span class="nl">animated:</span><span class="n">YES</span> <span class="nl">completion:</span><span class="o">^</span><span class="p">{</span> <span class="p">}];</span>
</span><span class='line'> <span class="p">}];</span>
</span><span class='line'>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>This will bring up the standard mail composer. All good. Now let’s look at making our own service. As Ole pointed out, Apple provide hidden applications/services (via SBAppTags in the Info.plist) which are started when a remote view controller is needed. So if you run the above code you’ll see a process called MailCompositionService is started (if it’s not already there). If we look inside the app bundle for MailCompositionService you’ll see some interesting keys:</p>
<p><img src="http://www.lyonanderson.org/images/mailComposerInfoList.png" alt="" /></p>
<p>It would appear as though SBMachServices defines the name of the XPC service we are offering. The budle indetifier matches the name used in the call to [UIRemoteViewController requestViewController:connectionHandler:]. We can now create an application of our own and add these keys to our Info.plist. I created an app called TestRemote and used com.electriclabs.TestRemote as the bundle name. The app has nothing but a blank view to start with. If you start the app and look in the system console you’ll see this error:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="mi">08</span><span class="o">/</span><span class="mi">10</span><span class="o">/</span><span class="mi">2012</span> <span class="mi">17</span><span class="o">:</span><span class="mi">38</span><span class="o">:</span><span class="mf">39.736</span> <span class="n">backboardd</span><span class="p">[</span><span class="mi">10007</span><span class="p">]</span><span class="o">:</span> <span class="n">Ignoring</span> <span class="n">info</span> <span class="n">dictionary</span> <span class="n">key</span> <span class="n">SBMachServices</span> <span class="n">since</span> <span class="n">com</span><span class="p">.</span><span class="n">electriclabs</span><span class="p">.</span><span class="n">TestRemote</span> <span class="n">is</span> <span class="n">not</span> <span class="n">a</span> <span class="n">system</span> <span class="n">app</span>
</span></code></pre></td></tr></table></div></figure>
<p>More on this later… I now wanted to understand what MailCompositionService does when it’s started by iOS. To do this I used dtrace with the following program:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="nl">objc$1:</span><span class="n">_UIViewService</span><span class="o">*::</span><span class="n">entry</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'><span class="n">ustack</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>As you may know dtrace is very chatty, but after spending a while I could see a rough pattern of _UIViewService method calls:</p>
<ol>
<li>Create an intance of _UIViewServiceSessionManager</li>
<li>Call <em>startListener on the instance of </em>UIViewServiceSessionManager</li>
<li>Create an instance of _UIViewServiceXPCListener with constructor initWithName:connectionHandler:</li>
</ol>
<p>There were other XPC calls but they appeared to sit underneath the UIViewService calls. In my TestApp I added the following to didFinishLaunchingWithOptions:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nf">application:</span><span class="p">(</span><span class="n">UIApplication</span> <span class="o">*</span><span class="p">)</span><span class="nv">application</span> <span class="nf">didFinishLaunchingWithOptions:</span><span class="p">(</span><span class="n">NSDictionary</span> <span class="o">*</span><span class="p">)</span><span class="nv">launchOptions</span> <span class="p">{</span>
</span><span class='line'> <span class="c1">//....</span>
</span><span class='line'>
</span><span class='line'> <span class="n">NSBundle</span> <span class="o">*</span><span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSBundle</span> <span class="nl">bundleWithPath:</span><span class="s">@"/System/Library/Frameworks/Social.framework"</span><span class="p">];</span>
</span><span class='line'> <span class="p">[</span><span class="n">b</span> <span class="n">load</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'> <span class="n">Class</span> <span class="n">_UIViewServiceSessionManager</span> <span class="o">=</span> <span class="n">NSClassFromString</span><span class="p">(</span><span class="s">@"_UIViewServiceSessionManager"</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="n">self</span><span class="p">.</span><span class="n">serviceManager</span> <span class="o">=</span> <span class="p">[[</span><span class="n">_UIViewServiceSessionManager</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">_init</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'> <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">serviceManager</span> <span class="n">_startListener</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">//....</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Now I needed the parameters to the method call [_UIViewServiceXPCListener initWithName:connectionHandler:]. To do this I invoked the services of lldb. Get MailComposistionService started by running the code at the start and then attach lldb:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'> <span class="p">(</span><span class="n">lldb</span><span class="p">)</span> <span class="n">process</span> <span class="n">attach</span> <span class="o">-</span><span class="n">n</span> <span class="n">MailCompositionService</span>
</span><span class='line'> <span class="p">(</span><span class="n">lldb</span><span class="p">)</span> <span class="k">continue</span>
</span></code></pre></td></tr></table></div></figure>
<p>To set a breakpoint in a private method you need to get its address. You can dump the symbols as follows:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">(</span><span class="n">lldb</span><span class="p">)</span> <span class="n">target</span> <span class="n">modules</span> <span class="n">dump</span> <span class="n">symtab</span>
</span></code></pre></td></tr></table></div></figure>
<p>From the output search for ‘[_UIViewServiceXPCListener initWithName:connectionHandler’, you should see a line like this:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">[</span><span class="mi">26153</span><span class="p">]</span> <span class="mi">26153</span> <span class="n">Code</span> <span class="mh">0x0000000000596ae3</span> <span class="mh">0x00ac9ae3</span> <span class="mh">0x000000000000023d</span> <span class="mh">0x000e0000</span> <span class="o">-</span><span class="p">[</span><span class="n">_UIViewServiceXPCListener</span> <span class="nl">initWithName:connectionHandler:</span><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>
<p>The important bit is the address - 0x00ac9ae3. We can now set a breakpoint:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">(</span><span class="n">lldb</span><span class="p">)</span> <span class="n">breakpoint</span> <span class="n">set</span> <span class="o">-</span><span class="n">a</span> <span class="mh">0x00ac9ae3</span>
</span></code></pre></td></tr></table></div></figure>
<p>Now bring up the mail composer again, and you should see our breakpoint is hit:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="n">Process</span> <span class="mi">10859</span> <span class="n">stopped</span>
</span><span class='line'><span class="o">*</span> <span class="kr">thread</span> <span class="err">#</span><span class="mi">1</span><span class="o">:</span> <span class="n">tid</span> <span class="o">=</span> <span class="mh">0x1c03</span><span class="p">,</span> <span class="mh">0x00ac9ae3</span> <span class="n">UIKit</span><span class="err">`</span><span class="o">-</span><span class="p">[</span><span class="n">_UIViewServiceXPCListener</span> <span class="nl">initWithName:connectionHandler:</span><span class="p">],</span> <span class="n">stop</span> <span class="n">reason</span> <span class="o">=</span> <span class="n">breakpoint</span> <span class="mf">1.1</span>
</span><span class='line'> <span class="n">frame</span> <span class="err">#</span><span class="mi">0</span><span class="o">:</span> <span class="mh">0x00ac9ae3</span> <span class="n">UIKit</span><span class="err">`</span><span class="o">-</span><span class="p">[</span><span class="n">_UIViewServiceXPCListener</span> <span class="nl">initWithName:connectionHandler:</span><span class="p">]</span>
</span><span class='line'><span class="n">UIKit</span><span class="err">`</span><span class="o">-</span><span class="p">[</span><span class="n">_UIViewServiceXPCListener</span> <span class="nl">initWithName:connectionHandler:</span><span class="p">]</span><span class="o">:</span>
</span><span class='line'><span class="o">-></span> <span class="mh">0xac9ae3</span><span class="o">:</span> <span class="n">pushl</span> <span class="o">%</span><span class="n">ebp</span>
</span><span class='line'> <span class="mh">0xac9ae4</span><span class="o">:</span> <span class="n">movl</span> <span class="o">%</span><span class="n">esp</span><span class="p">,</span> <span class="o">%</span><span class="n">ebp</span>
</span><span class='line'> <span class="mh">0xac9ae6</span><span class="o">:</span> <span class="n">pushl</span> <span class="o">%</span><span class="n">ebx</span>
</span><span class='line'> <span class="mh">0xac9ae7</span><span class="o">:</span> <span class="n">pushl</span> <span class="o">%</span><span class="n">edi</span>
</span></code></pre></td></tr></table></div></figure>
<p>I found that there were no variables defined, using frame variable, so I had to fall back to registers. There is a great article <a href="http://www.clarkcox.com/blog/2009/02/04/inspecting-obj-c-parameters-in-gdb/">here</a> on how to do this. Basically on i386 you can get at self using ‘po <em>(id</em>)($ebp+8)’ and the first and second paramters using po <em>(id</em>)($ebp+16) and po <em>(id</em>)($ebp+20) respectively. A peek at self showed we are not quite far enough in:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">(</span><span class="n">lldb</span><span class="p">)</span> <span class="n">po</span> <span class="o">*</span><span class="p">(</span><span class="kt">id</span><span class="o">*</span><span class="p">)(</span><span class="n">$ebp</span><span class="o">+</span><span class="mi">8</span><span class="p">)</span>
</span><span class='line'><span class="p">(</span><span class="kt">id</span><span class="p">)</span> <span class="n">$0</span> <span class="o">=</span> <span class="mh">0x0a14c7a0</span> <span class="o"><</span><span class="nl">_UIViewServiceSessionManager:</span> <span class="mh">0xa14c7a0</span><span class="o">></span>
</span></code></pre></td></tr></table></div></figure>
<p>We want self to be an intance of <em>UIViewServiceXPCListener. So I stepped in a few more levels using ‘thread step-in’, until self was </em>UIViewServiceXPCListener. I could now look at the paramters:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">(</span><span class="n">lldb</span><span class="p">)</span> <span class="n">po</span> <span class="o">*</span><span class="p">(</span><span class="kt">id</span><span class="o">*</span><span class="p">)(</span><span class="n">$ebp</span><span class="o">+</span><span class="mi">16</span><span class="p">)</span>
</span><span class='line'><span class="p">(</span><span class="kt">id</span><span class="p">)</span> <span class="n">$3</span> <span class="o">=</span> <span class="mh">0x0a53eb80</span> <span class="n">com</span><span class="p">.</span><span class="n">apple</span><span class="p">.</span><span class="n">uikit</span><span class="p">.</span><span class="n">viewservice</span><span class="p">.</span><span class="n">com</span><span class="p">.</span><span class="n">apple</span><span class="p">.</span><span class="n">MailCompositionService</span>
</span><span class='line'><span class="p">(</span><span class="n">lldb</span><span class="p">)</span> <span class="n">po</span> <span class="o">*</span><span class="p">(</span><span class="kt">id</span><span class="o">*</span><span class="p">)(</span><span class="n">$ebp</span><span class="o">+</span><span class="mi">20</span><span class="p">)</span>
</span><span class='line'><span class="p">(</span><span class="kt">id</span><span class="p">)</span> <span class="n">$4</span> <span class="o">=</span> <span class="mh">0xbfffe840</span> <span class="o"><</span><span class="nl">__NSStackBlock__:</span> <span class="mh">0xbfffe840</span><span class="o">></span>
</span></code></pre></td></tr></table></div></figure>
<p>So no massive suprises, _UIViewServiceXPCListener expects a name which in the case of MailComposistionService is “com.apple.uikit.viewservice.com.apple.MailCompositionService” and a callback block. I’m not sure of the structure of the block, but I’m going to take a punt on it having two parameters. The first being a connection and the second an NSError.</p>
<p>I now extended my didFinishLaunchingWithOptions method of the service TestRemote to look like this:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nf">application:</span><span class="p">(</span><span class="n">UIApplication</span> <span class="o">*</span><span class="p">)</span><span class="nv">application</span> <span class="nf">didFinishLaunchingWithOptions:</span><span class="p">(</span><span class="n">NSDictionary</span> <span class="o">*</span><span class="p">)</span><span class="nv">launchOptions</span> <span class="p">{</span>
</span><span class='line'> <span class="c1">//....</span>
</span><span class='line'>
</span><span class='line'> <span class="n">NSBundle</span> <span class="o">*</span><span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSBundle</span> <span class="nl">bundleWithPath:</span><span class="s">@"/System/Library/Frameworks/Social.framework"</span><span class="p">];</span>
</span><span class='line'> <span class="p">[</span><span class="n">b</span> <span class="n">load</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'> <span class="n">Class</span> <span class="n">_UIViewServiceSessionManager</span> <span class="o">=</span> <span class="n">NSClassFromString</span><span class="p">(</span><span class="s">@"_UIViewServiceSessionManager"</span><span class="p">);</span>
</span><span class='line'> <span class="n">Class</span> <span class="n">_UIViewServiceXPCListener</span> <span class="o">=</span> <span class="n">NSClassFromString</span><span class="p">(</span><span class="s">@"_UIViewServiceXPCListener"</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="n">self</span><span class="p">.</span><span class="n">serviceManager</span> <span class="o">=</span> <span class="p">[[</span><span class="n">_UIViewServiceSessionManager</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">_init</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'> <span class="p">[</span><span class="n">self</span><span class="p">.</span><span class="n">serviceManager</span> <span class="n">_startListener</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'> <span class="n">self</span><span class="p">.</span><span class="n">serviceListener</span> <span class="o">=</span> <span class="p">[[</span><span class="n">_UIViewServiceXPCListener</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithName:</span><span class="s">@"com.apple.uikit.viewservice.com.electriclabs.TestRemote"</span> <span class="nl">connectionHandler:</span><span class="o">^</span><span class="p">(</span><span class="kt">id</span> <span class="n">arg1</span><span class="p">,</span> <span class="kt">id</span> <span class="n">arg2</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'> <span class="n">NSLog</span><span class="p">(</span><span class="s">@"Arg 1 %@, Arg 2 %@"</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'> <span class="p">}];</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'> <span class="c1">//....</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>So I’m expecting that when my service is needed I’ll get a callback on my connectionHandler and from there I can create an instance of our view controller. Communication between service and host will be via XPCObjects.</p>
<p>I then created a simple client app called TestRemoteClient. We’ll need a _UIRemoteViewController subclass
which I called ELTestRemoteViewController. For simplicity I created a simple view controller with a button which when pressed tries to create an instance of our remote view controller:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">-</span> <span class="p">(</span><span class="kt">IBAction</span><span class="p">)</span><span class="nf">openRemoteController:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="nv">sender</span> <span class="p">{</span>
</span><span class='line'> <span class="n">Class</span> <span class="n">UIRemoteViewController</span> <span class="o">=</span> <span class="n">NSClassFromString</span><span class="p">(</span><span class="s">@"ELTestRemoteViewController"</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="n">UIRemoteViewController</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="p">[</span><span class="n">UIRemoteViewController</span> <span class="nl">requestViewController:</span><span class="s">@"TestRemote"</span> <span class="nl">fromServiceWithBundleIdentifier:</span><span class="s">@"com.electriclabs.TestRemote"</span> <span class="nl">connectionHandler:</span><span class="o">^</span><span class="p">(</span><span class="kt">id</span> <span class="n">remoteViewController</span><span class="p">,</span> <span class="kt">id</span> <span class="n">error</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'> <span class="n">NSLog</span><span class="p">(</span><span class="s">@"Arg 1 %@, Arg 2 %@"</span><span class="p">,</span> <span class="n">remoteViewController</span><span class="p">,</span> <span class="n">error</span><span class="p">);</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="n">remoteViewController</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="p">[</span><span class="n">self</span> <span class="nl">presentViewController:</span><span class="n">remoteViewController</span> <span class="nl">animated:</span><span class="n">YES</span> <span class="nl">completion:</span><span class="o">^</span><span class="p">{</span> <span class="p">}];</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="p">}];</span>
</span><span class='line'>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>Unfortunately, I’ve never got this to work. I always get an error:</p>
<p> <code>
2012-10-08 15:15:05.357 RemoteViewControllerTest[5286:c07] Arg 1 (null), Arg 2 Error Domain=_UIViewServiceInterfaceErrorDomain Code=2 "The operation couldn’t be completed. (_UIViewServiceInterfaceErrorDomain error 2.)"
</code></p>
<p> Early I said I got an error when running the service app TestRemote - ‘Ignoring info dictionary key SBMachServices since com.electriclabs.TestRemote is not a system app’. As a last ditch I tried moving TestRemote into the iOS simulator’s main Application folder. Hoping it would be blessed as a system app. Note I had to reset the simulator after moving it so it appeared. Alas, this did not work however, the error did change when running the client app:</p>
<p> <code>
2012-10-08 14:31:58.635 RemoteViewControllerTest[2224:c07] Arg 1 (null), Arg 2 Error Domain=NSCocoaErrorDomain Code=581952 "The operation couldn’t be completed. (Cocoa error 581952.)"
</code></p>
<p> So there we are. I’m a bit stuck. Clearly, there are things missing. I don’t know where I am supposed to tell UIKit the name of my view controller on the service side, or the host interface. I expect i’d have to this in the connection handler block like thus:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="n">self</span><span class="p">.</span><span class="n">serviceListener</span> <span class="o">=</span> <span class="p">[[</span><span class="n">_UIViewServiceXPCListener</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithName:</span><span class="s">@"com.apple.uikit.viewservice.com.electriclabs.TestRemote"</span> <span class="nl">connectionHandler:</span><span class="o">^</span><span class="p">(</span><span class="kt">id</span> <span class="n">arg1</span><span class="p">,</span> <span class="kt">id</span> <span class="n">arg2</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'> <span class="n">NSLog</span><span class="p">(</span><span class="s">@"Arg 1 %@, Arg 2 %@"</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'> <span class="kt">id</span> <span class="n">serviceProxy</span> <span class="o">=</span> <span class="p">[[</span><span class="n">_UIViewServiceXPCProxy</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithConnection:</span><span class="n">arg1</span> <span class="nl">queue:</span><span class="n">dispatch_get_global_queue</span><span class="p">(</span><span class="n">DISPATCH_QUEUE_PRIORITY_DEFAULT</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="nl">target:</span><span class="p">[</span><span class="n">ELViewController</span> <span class="n">new</span><span class="p">]];</span>
</span><span class='line'>
</span><span class='line'> <span class="kt">id</span> <span class="n">operator</span> <span class="o">=</span> <span class="p">[</span><span class="n">_UIViewServiceViewControllerOperator</span> <span class="nl">operatorWithRemoteViewControllerProxy:</span><span class="n">serviceProxy</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'> <span class="p">}];</span>
</span></code></pre></td></tr></table></div></figure>
<p>I’d love to get this working.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Xcode can't find headers annoyance]]></title>
<link href="http://www.lyonanderson.org/blog/2012/10/04/xcode-cant-find-headers-annoyance/"/>
<updated>2012-10-04T15:37:00+01:00</updated>
<id>http://www.lyonanderson.org/blog/2012/10/04/xcode-cant-find-headers-annoyance</id>
<content type="html"><![CDATA[<p>Have you ever been in the situation where all of a sudden Xcode no longer finds certain header files in your project. Another symptom is a project that builds, but there are header import errors when you open a file. You’ve cleared derived data. You’ve checked your paths. You’ve said 10 Hail Marys. Yes, we’ve all been there. Last time this happened - today - I did try an old trick.</p>
<!-- more -->
<p>First, I entered the following into terminal and restarted Xcode.</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>defaults write com.apple.dt.Xcode IDEIndexingClangInvocationLogLevel 3</span></code></pre></td></tr></table></div></figure>
<p>Fire up console app and delete the derived data for your project. Console will become really shouty with stuff like:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>04/10/2012 15:46:50.299 Xcode[70288]: IDEIndexingClangInvocation: ---- X/Redacted.m</span></code></pre></td></tr></table></div></figure>
<p>This is normal. However, you’ll probably find lines like these:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>04/10/2012 15:46:50.321 Xcode[70288]: IDEIndexingClangInvocation: [diagnostic]: Redacted.h:9:9: fatal error: 'Refacted.h' file not found
</span></code></pre></td></tr></table></div></figure>
<p>This is not normal. You’ll find that Redacted.h is in fact in your project. What the hell! Now you have to do some thinking. From Console.app, filter for Xcode and grab all of the lines into a text editor. Save the file, we’re going to need it. I called mine xcodelog.txt. Now run the following command on the said file:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sed -n "s/.*fatal error: '\(.*\)' file not found.*/\1/p" xcodelog.txt | sort | uniq</span></code></pre></td></tr></table></div></figure>
<p>You should now have a long list of files. Here is the boring part. You’re looking for cyclic imports involving these files. Good luck with that. A common problem is a header file imported by your prefix file, then explicitly imported in another source file. You should not do this. Think carefully about your imports. When you’re done turn off the logging and restart Xcode:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>defaults delete com.apple.dt.Xcode IDEIndexingClangInvocationLogLevel</span></code></pre></td></tr></table></div></figure>
<p>If someone can shed light on why this happens, please get in touch.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[TypeScript]]></title>
<link href="http://www.lyonanderson.org/blog/2012/10/01/typescript/"/>
<updated>2012-10-01T22:14:00+01:00</updated>
<id>http://www.lyonanderson.org/blog/2012/10/01/typescript</id>
<content type="html"><![CDATA[<p>Microsoft have released a typed superset of JavaScript called <a href="http://www.typescriptlang.org">TypeScript</a>. I spent a sizable portion of my life looking at types and JavaScript, in particular <a href="http://pubs.doc.ic.ac.uk/authors/cla97/">Inferring types for JavaScript programmes</a>. I still find the area interesting, and it’s nice to see this new and exciting work. I wonder if TypeScript has a sound type system? I see already that someone on Twitter has <a href="https://twitter.com/puffnfresh/statuses/252816990782230528">pointed out</a> that arrays are mutable and covariant:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="kr">class</span> <span class="nx">A</span> <span class="p">{}</span>
</span><span class='line'>
</span><span class='line'><span class="kr">class</span> <span class="nx">B</span> <span class="kr">extends</span> <span class="nx">A</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">foo</span> <span class="p">()</span> <span class="p">{</span> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kr">class</span> <span class="nx">C</span> <span class="kr">extends</span> <span class="nx">A</span> <span class="p">{</span> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">var</span> <span class="nx">b</span><span class="o">:</span> <span class="nx">B</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[</span><span class="k">new</span> <span class="nx">B</span><span class="p">()];</span>
</span><span class='line'><span class="kd">var</span> <span class="nx">a</span><span class="o">:</span> <span class="nx">A</span><span class="p">[]</span> <span class="o">=</span> <span class="nx">b</span><span class="p">;</span>
</span><span class='line'><span class="nx">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">C</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'><span class="kd">var</span> <span class="nx">boom</span><span class="o">:</span> <span class="nx">B</span> <span class="o">=</span> <span class="nx">b</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
</span><span class='line'><span class="nx">boom</span><span class="p">.</span><span class="nx">foo</span><span class="p">();</span> <span class="c1">// boom points to an instance of C which has no foo method!</span>
</span></code></pre></td></tr></table></div></figure>
<p>When you run the above you’ll get an error stating that Object #<C> has no method ‘foo’. The Java type system also has covariant arrays, but would prevent the assignment on line 11 at runtime:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">A</span> <span class="o">{</span>
</span><span class='line'> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span> <span class="n">args</span><span class="o">[])</span> <span class="o">{</span>
</span><span class='line'> <span class="n">B</span><span class="o">[]</span> <span class="n">b</span> <span class="o">=</span> <span class="k">new</span> <span class="n">B</span><span class="o">[</span><span class="mi">2</span><span class="o">];</span>
</span><span class='line'> <span class="n">A</span><span class="o">[]</span> <span class="n">a</span> <span class="o">=</span> <span class="n">b</span><span class="o">;</span>
</span><span class='line'> <span class="n">a</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">=</span> <span class="k">new</span> <span class="n">C</span><span class="o">();</span> <span class="c1">// Runtime exception: Exception in thread "main" java.lang.ArrayStoreException: C</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">class</span> <span class="nc">B</span> <span class="kd">extends</span> <span class="n">A</span> <span class="o">{}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">class</span> <span class="nc">C</span> <span class="kd">extends</span> <span class="n">A</span> <span class="o">{</span> <span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[iOS6 Detailed Battery Info]]></title>
<link href="http://www.lyonanderson.org/blog/2012/09/27/ios6-detailed-battery-info/"/>
<updated>2012-09-27T11:32:00+01:00</updated>
<id>http://www.lyonanderson.org/blog/2012/09/27/ios6-detailed-battery-info</id>
<content type="html"><![CDATA[<p>I was poking around in the iOS6 private frameworks over the weekend and found some interesting battery related stuff. I’ve put together a quick and dirty app which displays most of the interesting stuff. You can get it on github <a href="https://github.com/lyonanderson/BatteryInfo">here</a>. Being ever so fashionable I only support iOS6. Plus, it doesn’t work on iOS5!</p>
<p><img src="http://www.lyonanderson.org/images/IMG_4055.png" alt="Screenshot" /></p>
<!-- more -->
<p>Delving deeper, there is a class called OSDBattery which exposes battery metrics including the battery cycle count and serial number. Looking at the <a href="https://github.com/nst/iOS-Runtime-Headers/">header dump</a> of iOS6 shows OSDBattery in the FactoryDiags framework. However, on device you won’t find this framework. Instead, you need to load the GAIA framework to use OSDBattery. So for example, to get the battery cycle count:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="n">NSBundle</span> <span class="o">*</span><span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSBundle</span> <span class="nl">bundleWithPath:</span><span class="s">@"/System/Library/PrivateFrameworks/GAIA.framework"</span><span class="p">];</span>
</span><span class='line'><span class="kt">BOOL</span> <span class="n">success</span> <span class="o">=</span> <span class="p">[</span><span class="n">b</span> <span class="n">load</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="n">success</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="n">Class</span> <span class="n">OSDBattery</span> <span class="o">=</span> <span class="n">NSClassFromString</span><span class="p">(</span><span class="s">@"OSDBattery"</span><span class="p">);</span>
</span><span class='line'> <span class="kt">id</span> <span class="n">powerController</span> <span class="o">=</span> <span class="p">[</span><span class="n">OSDBattery</span> <span class="n">sharedInstance</span><span class="p">];</span>
</span><span class='line'> <span class="n">NSLog</span><span class="p">(</span><span class="s">@"Battery Cycle Count %d"</span><span class="p">,</span> <span class="p">[</span><span class="n">powerController</span> <span class="n">_getBatteryCycleCount</span><span class="p">]);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>It goes without saying that you can’t submit an app using this code! It’s a private framework. Don’t be an idiot. I’m not sure how useful all of this is. I’d quite like to run the app on a refurbished device to see what is says. I’m also not clear as to where exactly the count is stored i.e. in the battery or on device. Maybe the <a href="http://www.ifixit.com">iFixit</a> guys can swap batteries in a device and let me know?</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Zeebox Launches in the US]]></title>
<link href="http://www.lyonanderson.org/blog/2012/09/27/zeebox-launches-in-the-us/"/>
<updated>2012-09-27T09:40:00+01:00</updated>
<id>http://www.lyonanderson.org/blog/2012/09/27/zeebox-launches-in-the-us</id>
<content type="html"><![CDATA[<p>After many months of hard work Zeebox has finally launched in the US. This coincides with a new UK release too. We’ve added a load of great new features including a What’s Hot section, an activity feed to see what you’re friends have been doing, and a great new commenting system. Electric Labs has been working with Zeebox since July last year - how time flies! You can grab the UK version <a href="http://itunes.apple.com/us/app/zeebox/id454689266?ls=1&mt=8">here</a> and the US version <a href="http://itunes.apple.com/us/app/zeebox/id513267737?ls=1&mt=8">here</a>.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Facebook Hack 2012 London Winners]]></title>
<link href="http://www.lyonanderson.org/blog/2012/09/26/facebook-hack-2012-london-winners/"/>
<updated>2012-09-26T21:40:00+01:00</updated>
<id>http://www.lyonanderson.org/blog/2012/09/26/facebook-hack-2012-london-winners</id>
<content type="html"><![CDATA[<p>Last Friday I went to the Facebook London Hack 2012 with <a href="https://twitter.com/mattjgalloway">Matt</a>, <a href="https://twitter.com/michaelslater">Michael</a>, <a href="https://twitter.com/netproteus">Will</a> and <a href="https://twitter.com/stephenoldham">Steve</a>. Matt’s written a nice explanation of what we did on his <a href="http://www.galloway.me.uk/2012/09/facebook-world-hack-london-winners/">blog</a>. In a nutshell we made a Silent Disco Flashmob app called Flash Dance. We had a great time, met lots of cool people and worked in a camper van tent. Even better, we won best overall hack!</p>
<p><img src="http://www.lyonanderson.org/images/IMG_4032.JPG" alt="" /></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[You're asking for the wrong thing. When pull should be push.]]></title>
<link href="http://www.lyonanderson.org/blog/2011/01/09/2670466085/"/>
<updated>2011-01-09T00:00:00+00:00</updated>
<id>http://www.lyonanderson.org/blog/2011/01/09/2670466085</id>
<content type="html"><![CDATA[<p>There was a great <a title="discussion" href="http://www.bbc.co.uk/programmes/b00x7c36">discussion</a> on Radio 4 last week about freeing up National Rail Enquires (NRE) departure board data for developers to use. There were some great points made by both sides. But the whole thing was quite black and white and didn’t really go into the more delicate and interesting issues. I often find in these discussions that people conflate a feed being publicly available and having permission to use that feed. They also conflate a feed with static data. Nonetheless, it’s great to have these discussions out in the open in a civilised and constructive manner.</p>
<!-- more -->
<p>First, I’d like to make my background clear. In 2008 I worked for a company called Kizoom. Kizoom had been creating mobile applications, mobile websites and websites with train information for nearly 10 years. We’d had a long standing license with NRE to do this. In November 2008 I released MyRail Lite to the Apple AppStore. It displayed departure boards and calling patterns for UK trains. It was a moderate success and many people liked it. It was free too. We removed the application from the store in December 2008. I don’t want to go into the details of that here. It’s not really relevant to this discussion. However, I learnt many things from the episode. I learnt how to make iPhone applications. I learnt that business can be very personal. Personal in terms of making a connection with customers. Personal in terms of business relationships; both good and bad ones. MyRail Lite opened many doors and not long after I got to work on thetrainline’s iPhone application. Something I still do today. So on balance it was a great thing. It heartens me today that people still talk about it.</p>
<p>So, back to the National Rail Enquires data. To be honest, departure boards are not particularly interesting and the scope for doing exciting things is a little limited. It almost feels that once you’ve seen one departure board app, you’ve seen them all. [That’s a bit unfair, as the same does not seem to be true of Twitter clients]. I’m not saying you can’t do interesting things with departure board data, just that there is a far more exciting feed available. As you may or may not be aware there is another way that NRE could give the data out to developers. Instead of the departure board, or pull feed as I shall call it, there is also a push feed. The push feed is like a fire hose (not sure what this means?) of train movements. As each train moves over sensors, periodically placed along the tracks, an event is generated (For more information see <a title="here" href="http://www.rail-reg.gov.uk/upload/pdf/rtti-decision-011209.pdf">here</a> [Page 9]). As you can imagine there are quite a lot of train movements. At Kizoom we saw the value of the push feed and built a really cool alerting engine with it. Internally we called it Clarence. On the outside we called it the Travel Angel. We could tell you when your train journey was going to be delayed via an SMS. We could even tell you when to get ready to change trains. We could do this because we knew where all the trains were. </p>
<p>Another more subtle advantage of the push feed is that it gives NRE better load independence with respect to the number of apps in the wild. Each app developer would be given a single push feed connection. It is then your job as a developer to handle the transformation of the feed into interesting information and scale appropriately. So if you want to build a departure board feed then you’ll have to handle the transformations and scalability yourself. NRE are protected as each developer only gets one push feed connection. With the current pull feed, each user of an application is making a connection to NRE’s servers.</p>
<p>Yes, it will be harder to work with. Yes, you won’t be able to simply plug your app into the feed and spit the data out. Yes, you’ll have to think about how you’re going to scale. But the rewards could be great. You could do things like infer problems on the lines, keep historical data and make pretty graphs. You could even create an alerting engine. You could analyse what happens to trains when the weather is bad. Maybe there are new ways to help commuters in these situations? Is it really helpful to tell people the next train is in 95 minutes from Waterloo? What does that really mean?</p>
<p>So to summarise, it’s great that NRE are giving out licences to the departure board feed. But what I’d really like to see is the push feed opened up. Because I believe that with the push feed we’ll really see what can be done with this data. Let’s aim higher and look beyond the departure board.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[My Year in Numbers]]></title>
<link href="http://www.lyonanderson.org/blog/2011/01/01/2557330270/"/>
<updated>2011-01-01T00:00:00+00:00</updated>
<id>http://www.lyonanderson.org/blog/2011/01/01/2557330270</id>
<content type="html"><![CDATA[<p>Here are some statistics for the year 2010 relating to me. Probably not that interesting, but here you go.</p>
<h2>Email</h2>
<p>My primary domain is lyonanderson.com. Most of my correspondence is via this account. I don’t include my work email here.<em> At work we recently moved to Lotus Notes so I suppose I no longer send email at work; we’ve to call them ‘notes’ instead. I don’t have any stats for that. I would imagine given the complexity of reading <strike>emails</strike> notes with Lotus Notes </em><em>getting statistics would almost be impossible. </em></p>
<p>Sent ~1400 messages (lyonanderson.com)<br/>Received ~6000 messages (lyonanderson.com)</p>
<p><img src="http://media.tumblr.com/tumblr_lecz28egyO1qawfwr.jpg"/></p>
<p>(The lower graph includes previous years, but I thought it was interesting to see how my email traffic is increasing year on year).</p>
<!-- more -->
<h2>SMS Usage</h2>
<p>So I’ve sent and received what I think is quite a large number of text messages. However, speaking to the yoof I had to revise this opinion. Kiddies today send this kind of traffic on a daily basis. </p>
<p>Sent: 3140 messages (35505 words)<br/>Received: 2965 message (42670 words) </p>
<p>Note I include ‘x’ as a word. It’s pronounced Kiss or Kiss Kiss. A kiss at the end of a SMS can make all the difference. Especially when sending SMSs to your boss. </p>
<p>Without giving too much away, the following two graphics depict the kinds of words I send in my SMS messages. I have not included ‘x’ in these pictures as no one wants to see a giant picture of an ‘x’.</p>
<p>Prominent words in outgoing SMS messages:</p>
<p><img src="http://media.tumblr.com/tumblr_leczettg1U1qawfwr.png"/></p>
<p>Prominent words in incoming SMS messages:</p>
<p><img src="http://media.tumblr.com/tumblr_leczg9j0Qr1qawfwr.png"/></p>
<h2>Twitter</h2>
<p>I posted 1021 twitter status updates. I would have done a graphic for this too, but everyone seems to be doing that. </p>
<h2>Evernote</h2>
<p>I like <a title="Evernote" target="_blank" href="http://www.evernote.com">Evernote</a> a lot. I throw all kinds of stuff in there. From receipts, instructions manuals and menus, to my personal diary entries (more on that later).</p>
<p>Notes create: 384</p>
<h2>Foursqaure</h2>
<p>I’ve not been using this as much as I wanted to. I think if more friends used it I would use it more. Still I like the idea and I think it’s going to go places in 2011. </p>
<p>Checkins: 223</p>
<h2>Running</h2>
<p>The most physical of the numbers in this list. I’ve really got into running this year. I love it. It does not love me. My knees have been quite bad recently so I’ve had to cut down lots. I use the Nike+ system to monitor my runs. </p>
<p>932.67 miles made of 146 runs.</p>
<p>The graph below shows how the runs were spread out over 2010. I went a bit crazy in the summer.</p>
<p><img src="http://media.tumblr.com/tumblr_lecztrWO5H1qawfwr.png"/></p>
<h2>Music</h2>
<p>I use Spotify for music. It’s worth £10 a month to have access to all that music. I use the iPhone client the most. I have all my Spotify clients scrobble to last.fm. Unfortunately, there is a big gap in the data for the beginning of the year. Sorry.</p>
<p>Tracks listened to: 8580</p>
<p>The graph below shows how the listening is spread out over the year. I’m not sure what the big spike is. I’ll look into that and get back to you.</p>
<p><img src="http://media.tumblr.com/tumblr_leczxaYYGe1qawfwr.png"/></p>
<h2>Stackoverflow.com reputation</h2>
<p>2010 saw me join stackoverflow.com. I like the site and had been using it as a spectator for a while. I decided to give something back by depositing my pearls of wisdom. As you can see from the graph I kind of got a little bored. I promise to be more active this year.</p>
<p><img src="http://media.tumblr.com/tumblr_led01oQPi31qawfwr.png"/></p>
<h2>Web Search</h2>
<p>Google can keep track of the web searches that you do. It’s quite scary, but looking back at the data can be interesting. I don’t have the tracking on all the machines I use for search, but the graphs below show the lion’s share. </p>
<p><img src="http://media.tumblr.com/tumblr_led040IKbn1qawfwr.png"/></p>
<h2>AppStore</h2>
<p>I have purchased the following applications for my iPhone/iPad from the iTunes AppStore.</p>
<blockquote>
<p>The Cloud Wi-Fi Finder, Labyrinth, Tumblr, NYTimes, Toiluxe - central London edition, Let’s Golf!, WorkSnug London, OffMaps, SnowRemote, BlockChalk, AudioBoo, Distances, defriended, Digg, Chambers Dictionary of the English language, Vodafone Navigation, Chambers Thesaurus, Instapaper Pro, WhatsApp Messenger, Gangstar: West Coast Hustle, I Am T-Pain, Nike True City, Flickit Pro, Sleep Cycle alarm clock, WordCrasher, Friend Focus, AutoStitch Panorama, Metro UK, allRadio, HourFace, Babelshot (photo translator), CameraBag, Advanced Bubble Level, StoreRanks, VirginTrains, PositionApp‚Ñ¢, ToonPAINT, Quickoffice Connect, Happening, Grand Theft Auto: Chinatown Wars, myStarbucks UK, Pocket Informant LITE (Calendar, VLC Remote £0.00, Chomp., DriveSaver, WhatBus, ooTunes Radio - Recording and Alarm Clock!, Digital SLR Photography Toolkit For Dummies, iPlane - Leeds Bradford International Airport, Assassin’s Creed II: Multiplayer, The OscarsÆ, Zen Bound‚Ñ¢ Lite, NextBuses, MyBus, iSimples, Angry Birds, MicroCars, SpongeBob Diner Dash Lite, ScribbleLive, Opera Mini Web browser, We Rule, TrueHDR, Mapzen POI Collector, Plane Finder £0.00, Lonely Planet London City Guide, Lonely Planet Paris City Guide, Lonely Planet Istanbul City Guide, Lonely Planet Barcelona City Guide, Lonely Planet Amsterdam City Guide, Lonely Planet Rome City Guide, Lonely Planet Berlin City Guide, Lonely Planet Copenhagen City Guide, Lonely Planet Vienna City Guide, Lonely Planet Budapest City Guide, Lonely Planet Stockholm City Guide, Lonely Planet Munich City Guide, Lonely Planet Moscow City Guide, Vancouver Travel Guide - The Sights, mopho, iBooks, GoodReader for iPad, The Guardian Eyewitness, Evernote, Syncopy, Netflix, IMDb Movies & TV, TweetDeck for iPad, ABC Player, AdobeÆ Ideas 1.0 for iPad, eBay for iPad, Numbers, Mocha VNC Lite, Granimator - The Wallpaper Creator, Molecules, Instapaper Pro, Feeddler RSS Reader for iPad, Urbanspoon for iPad, Marvel Comics, TIME Magazine, TIME May 10, USA TODAY for iPad, Backgrounds HD, NPR for iPad, Wikipanion for iPad, PCalc Lite Calculator, Yahoo! Entertainment, Simplenote, Dropbox, Twitterrific for iPad, BBC News, ArtStudio for iPad, AIM for iPad, FlickStackr, StreamToMe, Amazon Mobile, sobees for Facebook, Pro HDR, MacUser Magazine, N.O.V.A. - Near Orbit Vanguard Alliance HD, NDrive UK & Ireland, Hipstamatic, WIRED Magazine, Pages, Air Video - Watch your videos anywhere!, GoodReader for iPad, Reeder for iPad, FatBooth, PhotoGrab, iMovie, SimCity‚Ñ¢, AgingBooth, Barcelona Metro 09, Eliminate:GunRange, Enigmo 2, Feathers Visage, You Gotta See This!, Camera+ ‚the ultimate photo app, ShutterSnitch, WolframAlpha, Nike+ GPS, Flight Control, Osmos, Plane Finder AR, The Secret of Monkey Island: Special Edition, Nigella Quick Collection, LogMeIn Ignition, Geometry Wars‚Ñ¢: Touch, Friendly - Facebook Browser, SABMobile, myNZB, .03 seconds Pro, traveline south & east, TuneIn Radio, TuneIn Radio, Scanner Pro: scan multipage documents, ReaddleDocs (documents/attachments viewer and file manager), LEGO Harry Potter: Years 1-4, Momento (Diary/Journal), COMMAND & CONQUER‚ RED ALERT‚ for iPad, SCRABBLE for iPad, SimCity Deluxe for iPad, TETRIS for iPad, TETRIS, ScrabbleÆ, RAGE HD, QI, The Incident</p>
</blockquote>
<h2>Diary Entries</h2>
<p>I use evernote to keep a basic kind of diary. I have made 26 entries this year. Again, I could do with doing more this year.</p>
]]></content>
</entry>
</feed>