tag:blogger.com,1999:blog-43662778843018898872014-10-14T08:01:20.163-07:00I learned something todayI program Android in C++.Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.comBlogger30125tag:blogger.com,1999:blog-4366277884301889887.post-81518926836527708862012-01-18T07:29:00.000-08:002012-01-18T07:56:16.762-08:00Darkness on the Internet<span style="font-family: inherit;"><span style="background-color: white; color: #333333; line-height: 18px;">Today is Stop SOPA day, with sites like Wikipedia going dark in protest. Google isn't going dark, but it's got a doodle about it, so you know it's got to be at least as important as, say, <a href="https://www.google.com/doodles/doraemon-2009">Doraemon</a>.</span></span><br /><span style="font-family: inherit;"><span style="background-color: white; color: #333333; line-height: 18px;"><br /></span></span><br /><span style="background-color: white; color: #333333; font-family: inherit; line-height: 18px;">Please take a moment to sign a petition or contact your congressperson about SOPA and PIPA. This is a complicated issue and there are two sides to every argument, but as an internet user I feel SOPA is a horrible idea.</span><br /><span style="font-family: inherit;"><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">To understand why SOPA is a bad idea, consider this analogy. Let's say I call you up on your T-Mobile phone, and leave you a voicemail. (I'll use voicemail as an example because it's stored on T-Mobile's servers.) As part of my voicemail message, I play you a bit off my new Lady Gaga CD. (I have to use Lady Gaga as an example, because I work for Google. Long story.) Let's assume for the sake of argument that this is illegal. Who is at fault?</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">Am I at fault for playing the song? To the extent that playing it was illegal, I'd say yes. Absolutely, I'm at fault. Punish me.</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">Are you at fault for listening? You know what, I'll bite. Let's punish you, too--you should have hung up as soon as you realized there was unauthorized Gaga on the line.</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;"><a href="http://www.gocomics.com/bloomcounty/1986/06/22/">Is T-Mobile at fault for storing my voicemeil</a>? Think for a minute about what that means. How exactly was T-Mobile supposed to prevent this infringement? There's only one way: eavesdropping on every single voicemail that is ever left by anyone that uses their system.</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">Quite aside from the privacy concerns, this is a logistical nightmare. They'd have to have an army of people listening in on every conversation that anyone ever made, ready to flip a kill switch the moment they heard "Poker Face." And that's an easy example. What if the infringement involved someone less famous, like Elvis Hitler or Toad the Wet Sprocket? What if I <i>am</i> Elvis Hitler, and I'm playing you a track from my long-awaited followup to "Disgraceland?" There's going to be a lot of judgment calls, and a lot of eavesdropping.&nbsp;</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">Now let's talk about punishment. In this analogy, SOPA would not only require T-Mobile to do the eavesdropping and make the judgment calls. It would also allow any entertainment company to shut off T-Mobile completely just on the allegation that infringement occurred. Until it proved itself innocent, T-Mobile would be unable to connect to the U.S. telephone system or use U.S. airwaves. (In this analogy I'm granting the government miraculous powers over the electromagnetic spectrum--which, if you think about it, is not much more far-fetched than the miraculous powers it would need to have in order to actually enforce SOPA the way Congress apparently thinks it can.)</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">Think about that for a minute: an entire company put on hold on the basis of an <i>allegation</i>&nbsp;by some media multinational. Millions of employees out of work. Tens of millions of customers who can no longer communicate. All in the name of stopping infringment.&nbsp;</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">Replace "T-Mobile" with "YouTube," "Facebook," or "Google" and that's SOPA.</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">Listen, I don't want to come across as a big leftie here, but here in America we don't shut companies down even when we have <i>solid proof</i>&nbsp;that they are <i>killing people</i>. Now we're talking about shutting down Internet businesses not because they did something wrong, and not even because we have proof of wrongdoing, but because some entertainment company <i>alleged</i>&nbsp;that that one of that company's <i>customers</i>&nbsp;did something that <i>might</i>&nbsp;be wrong.</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">And don't even get me started on the actual enforcement clauses, which would empower our government to set up its own Great Firewall. I don't want to sound like Glenn Beck, but folks, this is how liberty ends. Ask a Chinese friend what the Great Firewall is for. Unless they're really dialed into politics, chances are they'll tell you it's to keep out porn and terrorists. We in the West think we'd never stifle political dissent, but we'll do it in a heartbeat if instead of calling it "dissent" you call it "terrorism" or "indecency" or "infringement."</span><br style="background-color: white; color: #333333; line-height: 18px;" /><br style="background-color: white; color: #333333; line-height: 18px;" /><span style="background-color: white; color: #333333; line-height: 18px;">Whatever you think about copyright law, SOPA is not the right way to enforce it. Even if the entertainment industry is right (newsflash: they're not) and a lack of SOPA would cause the entertainment industry to wither up and die, would we really censor the entire Internet in order to keep those Jerry Bruckheimer movies coming every summer? Ben Franklin derided those who would trade liberty for safety. What would he think of those who ask us to trade essential liberties for continued access to mindless entertainment?</span></span><br /><span style="font-family: inherit;"><span style="background-color: white; color: #333333; line-height: 18px;"><br /></span></span><br /><span style="font-family: inherit;"><span style="background-color: white; color: #333333; line-height: 18px;">So please, contact your congressperson. Wikipedia has a <a href="http://en.wikipedia.org/wiki/Special:CongressLookup">search tool</a>&nbsp;to help you. Don't copy a form letter, write something short and succint and from the heart. Even if it's just a few words, write something. If you're an avid Internet user, SOPA is literally an attack on your way of life. Help put a stop to it.</span></span>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-66360420497072737862011-11-28T13:38:00.001-08:002011-11-28T13:43:08.580-08:00My first "official" Android Blog post......went live last week <a href="http://android-developers.blogspot.com/2011/11/making-android-games-that-play-nice.html">here</a>! It's about my own personal pet peeve, games that play audio when you're not playing them. One of my achievements this year has been to improve the technical standards for featuring on the Android Market; at this point, it's almost impossible to get a new title featured if it has this bug. Which means, of course, that part of my job is to send off emails to promising game developers, asking if they can fix this sort of issue so that we can feature their game. I'm hoping that publishing this sort of blog post will help.<br /><br />Stay tuned for more; in return for being allowed to title my post "Part I of a series," I had to commit to at least three more episodes. :-)Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-92021407726604408582011-09-19T12:13:00.000-07:002011-09-19T12:55:50.073-07:00Bug in LockFreePipeDmitry Vyukov, one of my fellow engineers at Google, pointed out a bug in the implementation of LockFreePipe that you can find here and there on the internet, for example <a href="http://dx9-occlusion-sample.googlecode.com/svn-history/r43/trunk/DXUT/Optional/DXUTLockFreePipe.h">here</a>. That reminded me that Bruce Dawson (who coauthored the original with me) had discovered this bug a while ago and tried to explain it to me, but at the time we didn't have the code in front of us and I didn't completely grok what he was trying to tell me.<br /><br />Anyway, this particular bug is simple: in Read(), after the call to memcpy(), there should be a barrier before the read pointer is updated. Otherwise the read pointer update can become visible before the memcpy is finished, giving the writer an opportunity to overwrite the memory before it's read.<br /><br /><br /><pre style="white-space: pre-wrap; word-wrap: break-word;"> unsigned long cbTailBytes = min( bytesLeft, c_cbBufferSize - actualReadOffset );<br />#ifdef _XBOX_VER<br /> XMemCpy( pbDest, m_pbBuffer + actualReadOffset, cbTailBytes );<br />#else<br /> memcpy( pbDest, m_pbBuffer + actualReadOffset, cbTailBytes );<br />#endif<br /> bytesLeft -= cbTailBytes;<br /><br /> if( bytesLeft )<br /> {<br />#ifdef _XBOX_VER<br /> XMemCpy( pbDest + cbTailBytes, m_pbBuffer, bytesLeft );<br />#else<br /> memcpy( pbDest + cbTailBytes, m_pbBuffer, bytesLeft );<br />#endif<br /> }<br /><br /><span class="Apple-style-span" style="color: red;">// OOPS: no barrier here. These operations could be reordered</span></pre><pre style="white-space: pre-wrap; word-wrap: break-word;"><span class="Apple-style-span" style="color: red;">// by the compiler or by the CPU. Should have lwsync or _ReadWriteBarrier here.</span><br /> readOffset += cbDest;<br /> m_readOffset = readOffset;</pre><br />Dmitry also pointed out that a store-release is meaningless without a load-acquire, so there should also be a barrier in Write() after m_readOffset is read:<br /><br /><br /><pre style="white-space: pre-wrap; word-wrap: break-word;"> bool __forceinline Write( const void* pvSrc, unsigned long cbSrc )<br /> {<br /> // Reading the read offset here has the same caveats as reading<br /> // the write offset had in the Read() function above. <br /> DWORD readOffset = m_readOffset;</pre><pre style="white-space: pre-wrap; word-wrap: break-word;"><span class="Apple-style-span" style="color: red;">// OOPS: need lwsync or _ReadWriteBarrier here if we want it to work</span><br /> DWORD writeOffset = m_writeOffset;</pre><br /><br />Needless to say, I'm humiliated :-) and curious to know why this worked so well in the past. My first guess was that MSVC did not reorder because the read pointer was marked volatile. Of course, that raises the question of whether <i>any</i>&nbsp;of our barriers were necessary, if volatile is so magic. Well, yes, they were; MSVC volatile semantics at the time prevented compiler reordering, but didn't insert any barriers at the CPU level. The write could still have become visible any time before the read was issued. So why didn't it?<br /><br />I'd say we got lucky. Just because the CPU <i>can</i>&nbsp;reorder stores before reads, doesn't mean that it <i>does</i>. There's a good reason for the PowerPC to delay stores--it's something that can usually be deferred until later, because in general nobody's really waiting for a store to complete. (If the data is getting reused, it's probably in one of the PPC's copious number of registers. And if it's not... see "load-hit-store.") There's seldom a good reason for a read to get delayed, because the read is very frequently a dependency of the next instruction in the queue. I'm speaking very generally and in a fashion that involves waving my hands quite a lot, but the point is that the window for failure on this is pretty small. Not, however, small enough to be nonexistent, which is what you need if you're doing lock-free work. Bummer.<br /><br />The sad thing is that I really like this class. It's small and lightweight, doesn't do any allocation, and is basically perfect for things like passing data in and out of audio routines where blocking would cause glitches. I originally wrote it to dump sample data out of custom DSP routines on the Xbox 360, and it worked awesomely well for that purpose. But after talking to Dmitry, I realize that it really only worked &nbsp;as well as it did because of quirks in the 360's CPU architecture. It's not a generic piece of code.<br /><br />In any case, if you're using this class, please fix it by inserting memory barriers as described in the code snippet above. And stay tuned--there may be other bugs that I haven't found yet.Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-69816518703752336952011-09-10T17:35:00.001-07:002011-09-10T17:35:45.200-07:00My current frustration<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-N8PYB9uJhNc/TmwCP_9CEKI/AAAAAAAAAHw/GvaqJ-om45g/s1600/java+generics.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://4.bp.blogspot.com/-N8PYB9uJhNc/TmwCP_9CEKI/AAAAAAAAAHw/GvaqJ-om45g/s320/java+generics.jpg" width="320" /></a></div><br />Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-78837348714239706042011-09-06T14:00:00.000-07:002011-09-06T14:00:03.137-07:00Checking In...I haven't been good about posting to this blog lately, probably because I originally started it to talk about the Android NDK, and I haven't been doing much of that lately. I've been jumping around to different parts of Android, trying to learn more about the entire system. But I've made what Tim Bray says is a fundamental blogging mistake, which is to only write about what you think your audience wants to hear. Oops. I guess I should really start writing about what I've been doing, whether or not it's NDK-related (or even Android related).<br /><br />What I've mostly been working on, besides the inevitable "partner support" email queue, is a Google Tasks app. Yeah, I know, not groundbreaking. But all of the apps I've found so far do it wrong. They don't authenticate with my Google account token--instead, they ask me for my actual Google credentials, which I'm not going to give them. And they don't sync correctly. I want a Tasks app that's as solid as the Gmail app, and since I have the code to the Gmail app, I think I ought to be able to do it. I've got most of the account management stuff worked out, and I have access to the GTasks API (which is, by the way, kind of incomplete), and now I'm writing a ContentProvider so that I can hook it to a SyncAdapter and make background sync work. That's taken me down a path of inventing a lightweight ORM so that I can write a ContentProvider without having to do a whole lot of redundant keyboarding. (I almost said "typing," but that's an overloaded term in this context.)<br /><br />So that's probably what I'll be writing about for the next little while: my quixotic attempt to do a simple Android app The Right Way. I want it to be a shining example in every possible way. I've already found a few places where that's going to be impossible, because no Right Way exists. But that's a subject for another post...Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-6517514504233782352011-08-08T15:00:00.000-07:002011-12-01T15:07:31.586-08:00Ndk-gdb and service processes don't (currently) mix<div>Got a bug from one of our partners complaining that they had two almost identical Android projects, but one of them was debuggable and the other one wasn't. After checking all the usual culprits, we finally narrowed it down to a single line in the manifest of the undebuggable project (names have been changed, obviously):</div><div><br /></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="m">&lt;</span><span class="t">service</span> <span class="t">android:name</span><span class="m">="</span><b>com.somemiddleware.SomeUsefulService</b><span class="m">"</span><span class="t"> android:process</span><span class="m">="</span><b>:com.somemiddleware.useful.process</b><span class="m">"</span><span class="m"> /&gt;</span></span></div><div><br /></div>It was, of course, very tempting to blame the SomeMiddleware company and its purportedly Useful service, but it wasn't their fault at all. Instead, it turned out to be a very small error in one of the ndk's awk scripts. It turns out that the script that finds the pid of the process you're supposed to be debugging (extract-pid.awk) was, for various reasons, doing a substring match on the process name. This almost always works, because there's almost always only one process running under your package name at any one time. But it doesn't <i>always</i>&nbsp;work.<br /><div><br /></div><div>In this case we were bitten by a quirk of the Android service architecture. The manifest is allowed to specify a process name under which to run the service by using the android:process attribute. Normally this just specifies the exact name of the process that the service should run under. But there's a special case: if the process name so specified begins with a colon, then the service process is considered "private" and its name is concatenated with that of the main process. So instead of running as "com.somemiddleware.useful.process" the service runs as "com.mycompany.mygame:com.somemiddleware.useful.process."</div><div><br /></div><div>See the problem? Now we have two processes that match our package id: our main game process that runs as "com.mycompany.mygame" and the middleware service that runs as&nbsp;"com.mycompany.mygame:com.somemiddleware.useful.process" -- and guess which one gets matched by the ndk-gdb awk script?&nbsp;</div><div><br /></div><div>The fix to extract-pid.awk is simple, and I've already submitted a patch, so hopefully that'll get accepted and shipped in the next NDK. Meanwhile, if you happen to run into this bug, you can either patch the script yourself, or you can just eliminate the colon from the beginning of your service process name while you're debugging.</div><div><br /></div><div>If you're interested, here's a gnu diff version of the patch:</div><div><br /></div><div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">25,27d24</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&lt; # NOTE: For some reason, simply using $9 == PACKAGE does not work</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&lt; # &nbsp; &nbsp; &nbsp; with this script, so use pattern matching instead.</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&lt; #</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">31a29</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&gt; &nbsp; &nbsp; RS = "\r\n"</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">40c38</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&lt; &nbsp; &nbsp; gsub("\\.","\\.",PACKAGE)</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">---</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&gt; &nbsp; &nbsp; #gsub("\\.","\\.",PACKAGE)</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">46c44</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&lt; $9 ~ PACKAGE {</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">---</span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&gt; $9 == PACKAGE {</span></div></div><div><br /></div><div><br /></div>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-57190924911157302252011-07-12T11:33:00.000-07:002011-07-12T11:33:56.278-07:00Yes, I am now on Google+<a href="https://plus.google.com/109486821799932251955/posts">Of course.</a>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-31483212464596897992011-07-08T10:38:00.000-07:002011-07-08T10:38:37.106-07:00Anyone want to do some Android ports?A friend of mine is looking for a team to port a couple of titles to Android. Email me if you're interested: i lewis at google dot com.Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-16173031869135922232011-05-27T08:36:00.000-07:002011-09-06T13:49:14.354-07:00I'm slowly learning to hate Eclipse lessI'm doing more development on my Mac, which means more Eclipse. Of course I hate it. I've been using Visual Studio since 1998, and Turbo C++ before that, and compared to those IDEs Eclipse feels like... well, it feels like Linux. There's no better way to put it. It feels like a hodgepodge of great ideas put together by a large number of incredibly smart people with almost no coordination whatsoever.<br /><div><br /></div><div>Fortunately I work with a large number of people who are both smarter and more patient than myself, so I was able to get help. <a href="http://twitter.com/#!/fredsa">Fred Sauer</a>, better known as one of the minds behind <a href="https://chrome.google.com/webstore/detail/aknpkdffaafgjchaibgeefbgmgeghloj?utm_campaign=en&amp;utm_source=ha-en-na-us-webapp-angrybirds&amp;utm_medium=ha">Angry Birds Chrome</a>, sat down and shared some tips that ended up making a huge difference to me. Here's a selection of the tips that helped me the most:</div><div><br /></div><div><ol><li>Eclipse "workspaces" are pretty much just like Visual Studio solutions. They seem different and weird at first, because (a) they're directories, not files, and (b) Eclipse makes you choose one at startup. But end of the day, they're just containers for projects.</li><li>"Close Unrelated Projects" is the magic command to unclutter your workspace--it closes up every project that doesn't live in the dependency chain of the project you're currently working on. Nice!</li><li>Command+3 (Ctrl+3 on Windows) is your friend. It brings up a quick search of all menu items, keyboard commands, and shortcuts. This is one Eclipse feature I really wish Visual Studio had--I use it all the time and it makes learning the IDE far easier. Unless, of course, you don't know what the command you want is named....</li><li>The command I want most but couldn't figure out the name for: Backward History. It's the rough equivalent of Ctrl+Tab in Visual Studio. There's also a Forward History.</li><li>Eclipse builds all the time by default. You can turn this off in the Project menu, at which point Ctrl+B does what F7 does in Visual Studio.</li></ol><div>Thanks to Fred's tips--especially the one about Command+3--I've been able to use Eclipse for a week or two now without wanting to chew off my own arm and use it to club people to death. So that's an improvement. I won't say I love Eclipse--I doubt I ever will--but I'm coming to terms with it. If I find any more useful tips I'll post them here.</div></div>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com1tag:blogger.com,1999:blog-4366277884301889887.post-52543411028597042922011-05-18T22:03:00.000-07:002011-12-01T15:06:18.885-08:00NDK debugging without root access<a href="http://ian-ni-lewis.blogspot.com/2011/05/victory.html">Recently</a>&nbsp;I made a comment to the effect that while ndk-gdb enables debugging on unrooted devices, Nvidia's Eclipse plugin and WinGDB's Visual Studio plugin don't. This means that if you want easy, IDE-based device debugging today, you need to start by running "adb root". Maybe that doesn't seem like a problem if you've already rooted your phone or if most of your debugging is done on an emulator. But if you're trying to develop on your personal phone, and it's a subsidized phone from a carrier that locks out root access, and you're trying to debug something the emulator doesn't support (<i>cough, OpenGL 2, cough</i>) this is kind of a big deal. Even if you've got a rooted device, why run as root if you don't have to?<br /><br />This isn't meant as a criticism of either NVidia or the WinGDB folks. WinGDB has explicitly said they're only supporting emulators right now, and NVidia is targeting its own devkits that have AFAIK always shipped rooted. I highly doubt that they tried and failed to debug without root, I just don't think that they've had any real reason to try. But I was surprised to see just how small of a change needs to be made in order to enable debugging on unrooted devices.<br /><br />The short answer to the question "how can I debug a process if I'm not root?" is simple: the debugger needs to run under the same account as the process it's debugging, and it can't do things (e.g. create sockets) which might be forbidden to that account. The long answer is more involved, because running under the same account isn't quite as simple as it sounds. To understand why this is tricky, let's first revisit how accounts and privileges work on Android.<br /><br />When it comes to restricting privilege, desktop OSes have nothing on Android. Windows, OSX, and Linux all have the concept of root and non-root accounts, but they apply these concepts mostly to users (although both consumer OSes have followed *nix's lead in allowing&nbsp;<a href="http://xkcd.com/149/">sudo</a>-style&nbsp;temporary privilege escalation, which while sometimes <a href="http://en.wikipedia.org/wiki/File:Windows_7_UAC.png">annoying</a>, at least prevents everyone from<a href="http://en.wikipedia.org/wiki/Windows_XP"> running as root all the time</a>). In general, every process the user runs has access to the same files and settings as any other process, give or take. Which means that "OpenOffice.exe" and "MalwareRiddenToolbarInstalledWithSomePornMyRoommateDownloaded.exe" have approximately equal ability to read, write and delete your stuff.<br /><br />Android takes a different tack, one that's more common in mobile systems: it creates a different account for each app. This has two immediate advantages. First, every app gets its own "home directory" that other apps can't access, so it's harder for programs to screw with each other. Second, it makes it easy for the system to customize a set of privileges for each application. Some apps need to access the Internet, write to your contacts list, and send SMS texts; others don't.<br /><br />But this compartmentalized security model makes life hard for gdbserver. While the underlying Linux permission model for debugging is pretty reasonable--as a normal user, you're allowed to debug any app that's running under the same account--that model assumes that accounts are tied to users or roles, not individual apps. What works on the desktop fails on Android because by default the app and the debugger will run under separate identities.<br /><br />As an example, here's me trying to run the command line that WinGDB issued for my most recent debugging session. I'm running it against an unrooted Xperia Play. (I extracted the command line using <a href="http://technet.microsoft.com/en-us/sysinternals/bb896645">ProcMon </a>.)<br /><br /><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&gt;adb shell&nbsp;</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/data/data/com.example.testwingdb/lib/gdbserver :1001 --attach 1221</span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>Cannot attach to process 1221: Operation not permitted (1)</b></span><br /><br /><br />No dice. The process I want to debug is running under the identity that's been assigned to com.example.testwingdb. But gdbserver is running under a different account--in this case, the default shell identity.<br /><br />So what to do? Well, it turns out that there is a simple way out of this mess. Android ships with a utility called run-as. The run-as command takes a package name and a command line, then turns around and executes that command line under the security identity of the package you named. It's just like sudo, except run-as lets you specify which identity you want to run under while sudo always uses root. [<b>Edited to add</b>: Some Android device builds have issues with run-as. See my comment (comment #3 below this post).]<br /><br />Here's me running the unix "id" command first without, then with "run-as". (For this example and the ones that follow, I'm using a package called com.example.testwingdb. If you're playing along at home, substitute your own package name.)<br /><br /><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&gt;adb shell id</span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>uid=2000(shell) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1009</b></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>(mount),1011(adb),1015(sdcard_rw),3001(net_bt_admin),3002(net_bt),3003(inet)</b></span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&gt;adb shell run-as com.example.testwingdb id</span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>uid=10117(app_117) gid=10117(app_117) groups=1003(graphics),1004(input),1007(log</b></span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>),1009(mount),1011(adb),1015(sdcard_rw),3001(net_bt_admin),3002(net_bt),3003(ine</b></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>t)</b></span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b><br /></b></span><br /><br />So we use run-as and all is dandy, right? Not quite yet.&nbsp;The last part of the trick is that the executable we want to run with run-as, in this case gdbserver, needs to be in a place where our app uid has permission to execute. Sharp-eyed readers may have noted that my instance of gdbserver lives in /data/data/com.example.testwingdb/lib. Fortunately for the lazier programmers among us, it's not there by accident. It got there because ndk-build automatically puts it there when it makes a debug build. It puts it there because that's where it needs to be if you want to run it under com.example.testwingdb's uid.<br /><br />With this in mind, we can make a very small tweak to the command line:<br /><br /><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&gt;adb shell run-as com.example.testwingdb /data/da</span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">ta/com.example.testwingdb/lib/gdbserver :1001 --attach 1221</span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>Attached; pid = 1221</b></span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b><br /></b></span><br /><span class="Apple-style-span" style="font-family: inherit;">Woohoo!! Gdbserver is launched and has successfully attached to my process. All is perfect.... well, until this happens:</span><br /><span class="Apple-style-span" style="font-family: inherit;"><br /></span><br /><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>Can't bind address: Permission denied.</b></span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>Exiting</b></span><br /><br />Here we see the second consequence of the Android security model: apps have fine grained permissions. In this case, my app never asked for Internet permissions, so it's unable to open a socket--and because gdbserver is running under my app's uid, it can't open sockets either.<br /><br />There's two ways to solve this. We could just modify our app manifest to request Internet permission. But that would suck: we don't need that permission for anything else, so we'd be making a significant change to our app's capabilities&nbsp;just to make it debuggable. A better solution is to do what ndk-gdb does: create a named pipe that gdbserver can use instead of a socket. Communication over named pipes doesn't require special permission as long as the pipe itself is accessible to the app, and adb includes the "forward" command that magically turns a device-side named pipe into a host-side socket:<br /><br /><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&gt;adb forward tcp:5039 localfilesystem:/data/data/com.example.testwingdb/debug-pipe</span><br /><br />To use the named pipe, we launch gdbserver like this:<br /><br /><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&gt;adb shell run-as com.example.testwingdb /data/da</span><br /><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">ta/com.example.testwingdb/lib/gdbserver +debug-pipe --attach 1221</span><br /><b><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Attached; pid = 1221</span></b><br /><b><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Listening on sockaddr socket debug-socket</span></b><br /><br /><br /><br />And BAM. We can now connect up our favorite gdb client to port 5039 on the host, and it will communicate with the device-side instance of gdbserver over the named pipe /data/data/com.example.testwingdb/debug-pipe.<br /><br />As far as I can tell, that's all it takes to enable rootless debugging. Let's review:<br /><br /><ol><li>Launch gdbserver under the uid of the process to be debugged, using run-as.</li><li>Tell gdbserver to use a named pipe instead of a socket to communicate with the host.</li><li>Use adb forward to forward the device-side named pipe to a host-side tcp socket.</li></ol><div>Hope that helps!</div>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com10tag:blogger.com,1999:blog-4366277884301889887.post-9844771156641773852011-05-16T22:46:00.000-07:002011-09-06T13:49:25.396-07:00Android talks from GDC......are now available online, mostly. And mostly in new improved form. We were able to get almost all of the talks accepted to Google I/O this year, and those sessions were taped. So check these out:<br /><br /><br /><ul><li>My talk, <a href="http://www.youtube.com/watch?v=5yorhsSPFG4">Bringing C and C++ Games to Android</a>, which I got to late and with an incredibly hoarse voice. Aaargh. Dan Galpin was my co-presenter and he covered for me on the first couple of slides. Thanks Dan! This talk is a good intro to the NDK, and also contains an overview of common pitfalls that we've seen in more than one game.</li><li>Dan's other talk, <a href="http://www.youtube.com/watch?v=TnSNCXR9fbY">Evading Pirates and Stopping Vampires</a>, covers nifty license server tricks for protecting your IP. This is especially important for games that host additional content (as in, the stuff that didn't fit in your apk) on the web. Nonpaying customers can suck your bandwidth bill and kill your profits if you don't take some precautions, but the Android license server can help protect you from these vampires as well as from more traditional pirates.</li><li>Nico Weber's <a href="http://www.youtube.com/watch?v=YLVbLVtjDDw">3D Graphics on Android: Lessons Learned from Google Body</a>. Nico ported Google Body to Android, and he pulls no punches when he talks about the issues he ran into. A must-see for anyone who's tackling serious OpenGL programming on the Android platform.</li><li>And the great Chris Pruett, no longer a Googler but still passionate about Android gaming, reprised his excellent presentation <a href="http://www.youtube.com/watch?v=cdvaPyq_eBU">Building Aggressively Compatible Android Games</a>. Check out Chris's new venture, <a href="http://robotinvader.com/blog/">Robot Invader</a>. He's already got a better blog than mine, so go over there and read his stuff now.</li></ul><div>Sorry to the audio fans out there--the Android audio team was busy writing code and couldn't come to I/O to present the OpenSL talk that they did at GDC. Bummer! We'll try and get Glenn and Jean-Michel out to another conference or Dev Day soon so we can get their talk on the Web.&nbsp;</div><div><br /></div>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-17463547046228996112011-05-16T22:09:00.000-07:002011-05-16T22:09:39.655-07:00Victory!I finally got the latest version of <a href="http://www.wingdb.com/wgMobileEdition.htm">WinGDB For Android</a> to really truly work. Best news: it's faster than the Eclipse debugger. A <i>lot</i>&nbsp;faster. So far it feels about as fast as the Xbox 360 debugger--not as fast as local, but very usable. So, about as good as you can expect from what is, after all, a remote debugger operating over a serial link.<br /><br />Just a few small snags in what is, after all, still a beta product:<br /><br /><ul><li>Your device has to be rooted. I think this is because nobody's quite figured out that you need to do some special things to run gdbserver as non-root. The ndk-gdb shell script does it right; WinGDB and the NVidia Eclipse plugin don't.</li><li>You have to run Visual Studio as administrator. I found this really surprising, since it's been possible for years to build a VS plugin that didn't require admin privileges to run. <a href="http://code.google.com/p/nativeclient-vsx/">Even a debugger replacement</a>.&nbsp;</li><li>I couldn't get WinGDB's "Deploy" option to work. Even when it said it worked, it turned out to have not in fact succeeded. Their website says this is due to an adb bug. I'm skeptical; I was able to "ant install" from my project directory quite reliably. On the other hand, I was just using ant to install to the default device, and they're trying to make sure the deployment goes to a specific device (the one you said you wanted to debug on), so maybe they're hitting an edge case that makes adb fall over.</li><li>Dependency checking seems to be nonexistent--doing anything seems to trigger a build of the world. And I mean anything, including pressing the "Debug" toolbar button.&nbsp;This is pretty annoying even when "the world" is a sample project with one source file in it. On an actual application, it will be crippling. If they fix nothing else, this has to be remedied.</li><li>Intellisense is broken. This sort of doesn't surprise me; the VS plugin mechanism makes it kind of hard to replace the native debugger and build system without replacing absolutely fucking <i>everything</i>. I was kind of hoping Visual Assist might step in and lend a hand, but no dice. From Visual Studio's point of view, you're not in C++ anymore, you're in some alien project that it has no hope of understanding. The good news is that the WinGDB folks know this and claim to have a fix in the works. I'll be really interested to see what they come up with.</li><li>And a smattering of small UI bugs that you'd expect from a beta build.</li></ul><div>All in all, not bad. The inability to do a minimal build has me worried, but I'm going to do a little poking around and see if it's something I'm doing wrong. If I can get it fixed, this might turn into my main debugging tool.&nbsp;</div>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com1tag:blogger.com,1999:blog-4366277884301889887.post-37222785293787917902011-04-27T12:04:00.000-07:002011-04-27T12:04:34.619-07:00Big life changes!<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-CUk1ZmrIu2w/Tbg-CS2sz-I/AAAAAAAAADI/NHRe3ndOrOM/s1600/IMG_20110425_221147.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://3.bp.blogspot.com/-CUk1ZmrIu2w/Tbg-CS2sz-I/AAAAAAAAADI/NHRe3ndOrOM/s320/IMG_20110425_221147.jpg" width="301" /></a></div>It's been a crazy few weeks for me. First and most importantly, our daughter Amanda Evelyn (Chinese name: Yilan) Ni-Lewis was born on April 9! Mother and baby are doing fine, although at 8lbs 8oz little Amanda was quite a burden on my not-so-large wife.<br /><br />Second, on the day before Amanda was born, I officially transferred to Android Developer Relations. I'd started out in Chrome and spent a few months covering the gap left by Mark DeLoura's departure as Game Developer Advocate lead, but I've been wanting to get back into a more technical and product-focused role. When my friend Chris Pruett quit Android to go chase his dreams, an opportunity opened up and I took it.&nbsp;So I'll be working much more closely with Android game developers now. I'm still helping to coordinate Google-wide game developer relations activities, but that'll be more of a 20% project for me from now on.<br /><br />I'm also taking the plunge and trying to learn to love Eclipse. I'm not sure how that's going to go. I'll keep you posted. :-)Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-59365887340615031592011-03-28T13:34:00.000-07:002011-05-16T23:46:35.557-07:00GDC slides, how do they work?[update: (versions of) (most of) these talks are <a href="http://ian-ni-lewis.blogspot.com/2011/05/android-talks-from-gdc.html">now online</a>!]<br /><br />tomaswoj writes, "I would love to see the presentation you gave on NDK/C++ in Android on GDC2011. You've mentioned that it will be up for d/l at some point of time. GDC already shares lots of this year presentations in their 'free' section, but yours is not among them. Does it mean, it will be in the pay area only? Or just overlooked? "<br /><br />So, here's the deal. Back in a more innocent time of my life (late February), I was under the impression that it would be fairly easy to get slides posted online. I thought it would be about as easy as getting them OK'd for GDC in the first place--a little tedious, but not that hard. Hah. I was wrong.<br /><br />First and foremost, game developer relations deals with multiple product teams, each of which has their own PR org. We have to make sure that each team is ok with what we're saying about their product. And in the case of posting slides online, we need to be sure that nothing can be taken out of context, because we don't have the luxury of explaining them or doing Q&amp;A. So Chrome, App Engine, YouTube, and Android all need to be cool with not just the slides, but with all of the many uses and misuses they might suffer as they get passed around on the web.<br /><br />Most of the product teams have signed off or requested small changes. But Android is different, and this is why the answer to @tomaswoj is not going to make him (or me) happy. See, Android is not a Google product in the way that Chrome or Gmail is a Google product. Android is a product of the Open Handset Alliance, which is an industry consortium involving many, many companies--carriers, hardware manufacturers, and so on. It's true that Google has an important role in the Android ecosystem, but it's not a lone wolf. The challenges of balancing the needs of all of the OHA's members make Android PR extra careful.<br /><br />All of which boils down to one sad fact: Android's policy, which I learned after the fact, is to release slides only if they are accompanied by video. And we did not have budget for video at Moscone. (It's a union shop--we couldn't just handycam it ourselves.)<br /><br />So, what's going to happen to those slides? Well, there is one possibility that I'm exploring. The developer relations team does have a budget for video production at Google I/O, which is happening in May. It turns out that many of the presentations my team is giving at I/O are very similar to the ones we gave at GDC. (One might even say we were recycling the material. I would respond, waste not, want not.) So there's a reasonably good chance that we can post the material online after I/O. <br /><br />Does this suck? Yes. I learned a sad lesson this month. I'm very sorry that others--our excellent speakers and the developers who need this material--have to suffer for my sins. We'll do what we can to make the material available in some way, as soon as we can. But I can't make any promises about the NDK talk or any other Android material.Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com2tag:blogger.com,1999:blog-4366277884301889887.post-62984499650897489752011-03-24T10:18:00.000-07:002011-03-24T10:20:24.286-07:00Handedness! Argh!This week I started hacking on <a href="http://www.unity3d.com/">Unity</a>, because all the cool kids are doing it. I wanted to see what all the fuss was about. So far I'm pretty impressed. I like the component-oriented architecture, which is&nbsp;<a href="http://big1.codeplex.com/">something</a>&nbsp;I've been lazily experimenting with since I left <a href="http://en.wikipedia.org/wiki/Offset_Software">Offset Software</a> eighteen months ago. One of the frustrating things about Offset (and many other engines) is the monolithic entity model: every entity has physics, audio, etc., whether it's needed or not. In Unity every entity starts out empty and you add components as necessary. I don't know much about the underlying code in Unity, so I don't know how far down the component-oriented thing goes, but it seems pretty promising so far.<br /><br />I also got a copy of Maya, because I was sick of trying to learn Blender and we ended up with an extra copy at work. W00t! So now I can kick it like a real artist. (If only I <i>were</i>&nbsp;a real artist. So far I've been able to create a bad copy of the ship from<i>&nbsp;<a href="http://en.wikipedia.org/wiki/Elite_(video_game)">Elite</a></i>, and that's about it.) And best of all, Unity imports Maya files directly. No exporter FTW!!!.....<br /><br />...and that's where the problems began. Because Maya is all about right-handed coordinates, and Unity is resolutely left-handed. And neither product seems to offer any feature that would fix this. Maya has a left-handed tangent space option, but nothing for actual world space. I can flip my models 180° in Maya (this works because they're symmetrical around Z), but that doesn't actually change the vertices in Unity--it just adds a 180° rotation to the model's transform. Which is useless, because that's the world transform--there's no "import space to model space" node that I can find. Useful things like the Unity follow-cam use that transform to figure out which way the model is pointed. This led to hilarity as I tried multiple ways of rotating the model in Maya, only to find that no matter how I rotated it, and no matter what orientation the model appeared to have in my Unity scene, the follow-cam always floated around to the exact same spot right in front of my little spaceship. (In case you're new to this, let me emphasize that the follow-cam is supposed to always be in <i>back</i>&nbsp;of what it's following.)<br /><br />I guess the right thing to do is probably to parent the model under some other game object, and let the parent-to-child transform take care of the handedness switch. (I still need to figure out how to load a Unity transform with a matrix that inverts Z, because doing a 180 around Y isn't going to cut it forever.) But it still chafes me that neither Maya nor Unity has a simple way to invert Z. This seems like the kind of problem that would crop up fairly frequently.<br /><br />Maybe someone reading this knows how to fix the handedness mismatch between Maya and Unity in a clean way?Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com2tag:blogger.com,1999:blog-4366277884301889887.post-73118849241784334402011-03-19T19:02:00.000-07:002011-03-19T19:02:24.566-07:00So close but yet so far...So WinGDB has a <a href="http://www.wingdb.com/wgMobileEdition.htm">beta </a>up of their "mobile edition," which is light years beyond the hacktastic preview I <a href="http://ian-ni-lewis.blogspot.com/2011/01/its-like-coming-home-again.html">wrote about</a> a couple of months ago. I installed it today and wow. This is what Android hacking on VS was meant to be. You can create projects via the normal new project dialog, you can start debugging with the normal play button, and all of the random settings and junk that we had to deal with before are <i>gone</i>.<br /><br />What's really scary-cool is that they're actually working within the NDK make system. The project file is not a .vcproj or an MSBuild file, it is Android.mk. You add a file to the project via Visual Studio, and that's where it lands. That means they have completely rewritten the storage part of the Visual Studio project system, which is kind of a big deal. I'm not sure if I agree 100% with the design (I'm actually kind of a fan of MSBuild, at least for Visual Studio stuff)*, but I have to respect that kind of work.<br /><br />Only problem is, right now it doesn't work! Not on my computer, anyway. It does what looks like a full and successful build, but then tells me that the build failed and refuses to launch the debugger. I turned diagnostics up to 11, but I can't find anything that even looks like a failure in my build log. Building from the command line via ndk-build works fine. But no luck getting Visual Studio to act like all is well. I'll ping the WinGDB guys, of course. I'd be interested to know if anyone reading this can get this to work. I must be doing something wrong, but I've tried this with both the NDK samples and a scratch project, and I'm not having any luck.<br /><br />Well, it's probably for the best. I'd promised myself this would be the weekend that I finally learned how to use <a href="http://www.unity3d.com/">Unity</a>. So I'll get onto that. Leave a comment if you get the WinGDB beta working better than I did...Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com2tag:blogger.com,1999:blog-4366277884301889887.post-11830835701189433432011-03-19T18:22:00.000-07:002011-03-19T18:22:26.852-07:00Weekend Blogging: a recipe hackThree weeks ago I made a soup with Lagunitas <a href="http://beeradvocate.com/beer/profile/220/1579">GnarlyWine</a>&nbsp;that was so astonishingly not vile that I wanted to share the recipe. Of course, I promptly forgot it--probably because the GnarlyWine was accompanied by a half liter of <a href="http://www.lagunitas.com/beers/hopstoopid.html">Hop Stoopid</a>, which did <i>not</i>&nbsp;go into the soup. (Neither did half the GnarlyWine, come to think of it.) So I have no recipe to remember that weekend by. In fact, I have very little memory of that weekend in general, except for a recollection of Hop Stoopid being one of the most awesome beers I've ever had.<br /><br />So this weekend I'm writing down what I remember of my most recent experiment. Alcohol was not involved--quite the opposite, in fact. I wanted to make Beef Burgundy in our new <a href="http://www.healthytraders.com/stainless-steel-gourmet-automatic-electric-pressure-cooker-p-3220.html">automatic pressure cooker</a>.&nbsp;But, the wife is pregnant, and pouring an entire bottle of wine into her beef stew sounded like a bad idea. Even if most of the alcohol did cook out, she'd kill me--she's very, very careful of our baby's health.<br /><br />So how to spice beef stew without wine? I stumbled upon what turned out to be an amazing mix: onion powder, balsamic vinegar, white truffle oil, and just a bit of cheap-ass Costco brown gravy mix. Oh, and some McCormick garlic Season-All, probably because I use so much of it that nothing tastes right without it. Here's the recipe I ended up with (all measurements are approximate):<br /><br />16 oz ribeye steak, cubed<br />1 lb bag frozen peas &amp; carrots<br />3 red potatos, also cubed<br />1 tbsp 10 year old balsamic vinegar<br />1 tbsp white truffle oil<br />1/2 tbsp onion powder<br />1/2 tbsp brown gravy mix<br />1 tsp garlic Season-All<br />1 tsp basil<br />1 tsp oregano<br />1 tbsp extra-virgin olive oil<br /><br />Combine in pressure cooker, pressure cook for 30 minutes (the auto cooker's "soup" setting) and stir vigorously to break up the potatoes a bit so they thicken the stew. Mwah!<br /><br />The pressure cooker really is amazing. The meat was so tender. Well, ok, it was USDA choice ribeye, so no real surprise there. But everything was better than it had any right to be after half an hour of cooking. It tasted like it had been slow cooking all day. All the juices and flavors were mixed--even the potatoes were flavorful all the way through. I didn't even want the thing, it was my wife's purchase, but now I'm totally sold.<br /><br />Oh man, you know what would go awesome with this? A bottle of burgundy. Good thing <i>I'm</i>&nbsp;not pregnant... :-)Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-22651883161353530132011-03-12T11:02:00.000-08:002011-03-12T11:02:37.060-08:00In case you're wondering...It's been a while since my last update, I know. I caught some kind of flu at GDC that's left me tired and weak. Didn't help that, due to missing our anniversary on Feb. 27, I'd promised my wife to spend Monday on whatever she wanted. That turned out to be moving lots of heavy furniture around to get ready for our baby and for her mom to come stay with us. So on top of the flu I threw my back out.<br /><br />Anyway, I'm still sick and doing more than answering email is pretty much beyond me at this point. But I do have a beta of WinGDB 2 and I'll hopefully get a chance to try it out before it actually gets released. So stay tuned :-)Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-19946714785370337252011-03-02T10:24:00.000-08:002011-03-08T10:25:46.669-08:00Another Open LetterAn Open Letter to whomever stole my Motorola Xoom tablet at GDC.<br /><br />Dear Sir or Madam:<br />You stole my stuff. You suck.<br /><br />Unless, of course, you use that Motorola Xoom to create a fantastic app for the Android Market. In which case, good on you and I'm glad you're a little lightfingered.<br /><br />:-)<br /><br />IanIanhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-71512313428760054452011-03-01T20:48:00.000-08:002011-03-01T21:01:59.715-08:00Letter to a Bike Thief<div class="p1">An open letter to whomever stole my bike from the rack at the Moscone Center last night.</div><div class="p2"><br /></div><div class="p1">Dear Sir or Madam,</div><div class="p1">First of all, <i>ha ha ha ha ha ha ha</i>. I hope you enjoy your new bike. Especially the way the chain falls off when you downshift. Or the way the right-hand shifter sticks and has to be yanked back with your thumb. Enjoy the slow leaks in both of the tires. And especially enjoy the way you'll have to pump up those leaky tires with two separate bike pumps, because one of the tires has a normal red-blooded American valve, and the other one has one of those elitist European things with the long stem and the little screw gadget on the end.&nbsp;</div><div class="p2"><br /></div><div class="p1">Second, let me just be the first to salute what I can only assume to be your giant, brass-cored, steel-belted, chrome-plated set of cojones. That bike was locked up right on Market Street in full view of thousands of convention-goers. Admittedly your average Game Developer Conference attendee isn't the most physically imposing specimen, but still. There's an awful lot of them, and they're going back and forth in that area all day and all night because they're diehard party animals. So bravo, sir or madam, you have got to be swinging a massive pair.</div><div class="p2"><br /></div><div class="p1">Lastly, I want you to understand just what this means to my life. You didn't just steal a reasonably nice but sensibly priced road bike from me. You took away my mode of transportation. That means I have to buy another bike. And that's five hundred to a thousand dollars that could have gone to pay for so many other things.&nbsp;</div><div class="p2"><br /></div><div class="p1">For example, will I now be able to convince my wife to let me buy a new Xbox 360, the new black one with that fancy new camera controller thingy, even though I already have like five 360s sitting in the garage waiting to get their red rings of death fixed? No. And I was <i>this close</i>&nbsp;to talking her into it, too, man. But now that money is bike money. So I will not be playing Dance Central using my body as a controller this month. There will be no evacuating the dance floor for me. I'm going to have to get by with a regular controller and a stupid white Xbox just like I did last month.&nbsp;</div><div class="p2"><br /></div><div class="p1">And it's not just the Xbox, either. A bike costs a lot of money. Will I be buying a stack of new games or a bunch of e-books this month? No, that's bike money now. Can I get my 1995 Acura Integra detailed and waxed 'til it shines like the top of the Chrysler building, like I was planning? Gonna have to wait until the bike's paid off. Will I be sipping Champagne and dining on the finest cuisine San Francisco has to offer? Well, yes, because I plan to expense that. But those new shoes that Baby needs? Bike.</div><div class="p2"><br /></div><div class="p1">Okay, thinking about it, my life is pretty good. You probably need the bike more than I do. After all, I still do have one Xbox that hasn't red-ringed yet, and I've always got my 1995 Acura Integra (last model year before they nerfed the engine control computer!) to fall back on.<br /><br />So enjoy the bike. You're the one that has to live with being a lousy thief.</div>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com1tag:blogger.com,1999:blog-4366277884301889887.post-27815313698621566352011-03-01T20:44:00.000-08:002011-03-01T20:44:37.798-08:00GDC: Coming up for airAfter 2.5 days of GDC I'm finally coming up for air a bit. It's going really well. Our Google sessions played to a nearly full house, and we've been turning people away from the Android sessions all day long.&nbsp;<div><br /></div><div>I spoke last night at the Social and Online summit about lessons we learned from Google TV, and again today at the Android dev day on the Android NDK. What do those topics have to do with each other? Nothing. What do I know about either of them? Well... let's just say I had a lot of studying to do.&nbsp;</div><div><br /></div><div>I actually co-presented both talks. The main speaker for the Google TV talk was Andrés Ferraté, who has given me two gifts in life: one, a much better understanding of Google TV, and two, the knowledge of how to type an 'é' on the Mac. (Everyone who knows Andrés learns how to type é at some point. It's kind of a thing with him.) Andrés put together the main slides and I stepped in to play the role of "guy who knows console gaming" to talk about how Google TV is not a console. It was a fun talk to give, very fluffy but entertaining. For me, at least.</div><div><br /></div><div>The talk today was much more technical. I played the role of "guy who will explain the basics of the NDK," which was right in line with the work I've done so far. I talked about the ins and outs of getting started and using the NDK on Windows, &nbsp;and introduced things that I've been talking about on this blog, like <a href="http://ian-ni-lewis.blogspot.com/2011/01/its-like-coming-home-again.html">WinGDB</a>&nbsp;and <a href="http://vs-android.googlecode.com/">vs-android</a>. Then Dan stepped up to the plate and laid down his unique brand of magic, otherwise known as "knowing pretty much everything there is to know about NDK programming." Go teamwork!</div><div><br /></div><div>So dev days are over, and I'm relieved. There were some gaffes but overall I'm pleased. Thanks much to everyone who attended!&nbsp;</div>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-63540808250886875562011-02-21T18:08:00.000-08:002011-02-21T18:08:35.072-08:00One week to go...I learned something today: putting on a show, even just a little corner of a show like <a href="http://google.com/gdc2011">Google Developer Days at GDC</a>, is <i>really hard</i>. Combine that with the fact that I somehow volunteered to give two talks, and write a bunch of content for our new website, and I'm just about worn out.<br /><br />I've definitely learned my lesson about the talks: next time I'll either volunteer to organize things or to develop original material, but not both. It's not that either one is difficult, or that I didn't have time for both; it's that the two activities are very different and trying to juggle both was mentally exhausting. Not to mention that it put me in the position of being both boss and worker--I was developing my own material (and blowing deadlines, natch) as I was also trying to crack the whip on other developers and try and get them to meet the same deadlines I was having trouble with. I've gotten better at the management gig over the last twenty years, but it's still really hard to push people to do something I'd have a hard time doing myself.<br /><br />But my slides are done (well, almost--a little extra polish never hurts), and rehearsals are almost over, and in a week we're going to put on a great show. And then I am going to go hide in a corner and write code for a couple of months. :-)Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com2tag:blogger.com,1999:blog-4366277884301889887.post-58684450429468586642011-02-13T18:14:00.000-08:002011-02-13T18:14:18.676-08:00GDCIf you've been following my twitter feed--or any of my coworkers' feeds--you've probably heard that we launched a <a href="http://www.google.com/events/gdc/2011/">GDC microsite</a>&nbsp;a few days ago. This was my first experience launching a site at Google, and overall it wasn't bad. We got Ryan Thomas, who designed the <a href="http://www.google.com/tv/">Google TV site</a>, to do the layout for us. Ryan is actually working on something a lot bigger for us, which we haven't yet announced, but he agreed to take a little time out of his busy schedule and put this together for us.<br /><br />If you haven't already, this would be a good time to check out google.com/gdc2011. Especially check out the <a href="http://www.google.com/events/gdc/2011/speakers.html">speaker bios</a>--it turns out we have more game developers working for Google than you might have thought! We'll probably be adding some latecomers, too, as some of the talks will have more than one speaker. For instance, Dave Springer is probably going to show up. Who's Dave Springer? Oh, he just founded a little company called Alias. You might have heard of it.<br /><br />Hope to see you all at GDC. Come check out the Google developer days--I can promise you it will be well worth your time.Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0tag:blogger.com,1999:blog-4366277884301889887.post-20429818744728422542011-01-26T20:14:00.000-08:002011-01-26T20:15:26.413-08:00In which I access a fileHola amigos! Sorry it's been so long since I rapped at ya, but shit's been going down, you know? Shit, in this case, being Google's GDC presentations--two dev days and a couple of sponsored sessions, twelve talks total. We finally have a schedule and with luck we might even be able to post it soon, woohoo!! Now if I could just get my slides done....<br /><br />But anyway... I got a little more time to work on Android NDK programming last night. I was planning to play around with VBOs a bit, but I got a little sidetracked. See, I wanted to load up my shaders from a file, like a human being, not put them in constant strings like some damn dirty ape. And files are kind of weird on Android, because everything goes in the apk. Getting stuff into the apk is super easy--just toss it in the "assets" directory, easy as pie--but getting stuff out is another story.<br /><br />OK, first I have to thank Jeebus that I'm using Gingerbread and NDKr5, because I don't actually need to play games in Java to get access to the apk. If you want to know how blessed you are to be living in 2011 instead of 2010, just check out the old instructions for apk access (h/t to <a href="http://twitter.com/#!/dagalpin">Dan Galpin</a>):<br /><br /><blockquote>Use the asset manager code to get an AssetFileDescriptor:</blockquote><blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&nbsp;&nbsp;AssetFileDescriptor afd =</span>&nbsp;</blockquote><blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&nbsp;&nbsp; &nbsp;context.getAssets().openFd("ToothyDroid.png")</span>;</blockquote><blockquote>Read the offset and length from the AssetFileDescriptor:</blockquote><blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&nbsp;&nbsp;long offset = afd.getStartOffset();</span></blockquote><blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&nbsp;&nbsp;long length = afd.getDeclaredLength();</span></blockquote><blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&nbsp;&nbsp;afd.close();</span></blockquote><blockquote>Get the APK file name:</blockquote><blockquote><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">&nbsp;&nbsp;context.getApplicationInfo().sourceDir;</span></blockquote><blockquote>Open the APK file at the specified offset and read the specified length. [Code omitted from original, because... why is that, Dan? Because it's a pain to write? ;-)]</blockquote><br />Yeah. Weird.<br /><br />Anyway, with r5 things get a lot simpler, because there's now an AssetManager library that lets you use the asset manager directly. If you're using NativeActivity and the native app glue, you even get your application's asset manager passed down from Java for free as part of the application class. So you end up with code that looks a lot saner:<br /><br /><span class="Apple-style-span" style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 11px;"><span class="whitespace">&nbsp;&nbsp;</span><span class="text">AAsset* pAsset = AAssetManager_open(ctx-&gt;app-&gt;activity-&gt;assetManager, "readme.txt", AASSET_MODE_UNKNOWN);</span><br /><span class="whitespace">&nbsp;&nbsp;</span><br /><span class="whitespace">&nbsp;&nbsp;</span><span class="text">const int count = 80;</span><br /><span class="whitespace">&nbsp;&nbsp;</span><span class="text">char buf[count + 1] = {0};</span><br /><br /><span class="whitespace">&nbsp;&nbsp;</span><span class="text">while (AAsset_read(pAsset, buf, count) &gt; 0) {</span><br /><span class="whitespace">&nbsp; &nbsp;&nbsp;</span><span class="text">LOGI(buf);</span><br /><span class="whitespace">&nbsp;&nbsp;</span><span class="text">}</span><br /><span class="whitespace">&nbsp;&nbsp;</span><span class="text">AAsset_close(pAsset);</span></span><br /><br />That's better, right? It at least feels something like a normal set of filesystem calls. Rock on!!<br /><br />Of course, it <i>isn't</i>&nbsp;a set of normal filesystem calls... which immediately makes me look ahead to the time when I'm going to want to access other filesystems (the SD card, for instance), and probably want to do so without having to plumb two different sets of file APIs all through my code. And while I'm at it, I probably want to abstract whether I'm even using a filesystem, or whether my files are in memory, or compressed, or streamed, or packed together in one huge bundle. I guess what I'm saying is, I've written enough data access code in my life to know that I'm going to want an abstraction layer at some point.<br /><br />And so I pull out my trusty stream implementation... and run smack dab into the NDK build system. Ah, but that is definitely a post for another day. And probably at least a slide or two in my GDC talk.<br /><br /><br /><br /><ul class="ul1"><ul></ul></ul>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com2tag:blogger.com,1999:blog-4366277884301889887.post-40498694503783225362011-01-18T13:29:00.000-08:002011-01-18T13:29:23.125-08:00Interview with TechWeb<div class="separator" style="clear: both; text-align: center;"><a href="http://www.jointhegamenetwork.com/img/site/logo_ubmTW.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://www.jointhegamenetwork.com/img/site/logo_ubmTW.png" /></a></div>UBM Game Network newsletter did an interview with me as part of their pre-GDC coverage. You can read the interview <a href="http://www.jointhegamenetwork.com/thismonth/011711.html?cid=JTGNN_011711#2">here</a>. This was the first interview I've done over email. I'm pretty pleased with how it turned out--a lot of what I wrote got cut, but I expected that, and what's left is pretty much my own words.&nbsp;<div><br /></div><div>I'm really excited about what we've got planned for GDC this year. We'll be doing two full days of presentations on Monday and Tuesday, and we'll have a booth on the show floor.&nbsp;</div><div><br /></div><div>I'm in charge of the presentation content, so I'm doing a lot of running around trying to get everyone to finish their slides on time. Of course people will be fixing things all the way up to the day of the show, but we have to at least <i>pretend</i>&nbsp;to have deadlines. :-) The content is shaping up pretty well. We've got some really in-depth technical talks on Android and Chrome both. Most of the really deep tech stuff is going to be presented by the engineers that actually implemented the systems we're talking about. Should be really good.</div><div><br /></div><div>If you want to hear more about GDC, or about game development at Google in general, you might want to follow @ilewis_goog on Twitter. I generally don't post more than a couple of times a week.</div>Ianhttp://www.blogger.com/profile/15703303217263175278noreply@blogger.com0