<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4366277884301889887</id><updated>2012-02-18T21:54:04.589-08:00</updated><category term='visual studio'/><category term='ndk'/><category term='Android NDK file IStream stream makefiles build'/><category term='audio'/><category term='android'/><category term='personal'/><category term='debugging'/><category term='GDC'/><category term='debugger'/><category term='politics'/><category term='internet'/><category term='eclipse'/><category term='gtasks'/><category term='run-as'/><category term='service'/><category term='blog'/><category term='root'/><category term='SOPA'/><title type='text'>I learned something today</title><subtitle type='html'>I program Android in C++.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>30</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-8151892683652770886</id><published>2012-01-18T07:29:00.000-08:00</published><updated>2012-01-18T07:56:16.762-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOPA'/><category scheme='http://www.blogger.com/atom/ns#' term='internet'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>Darkness on the Internet</title><content type='html'>&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;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, &lt;a href="https://www.google.com/doodles/doraemon-2009"&gt;Doraemon&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: white; color: #333333; font-family: inherit; line-height: 18px;"&gt;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.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;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?&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;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.&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;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.&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;&lt;a href="http://www.gocomics.com/bloomcounty/1986/06/22/"&gt;Is T-Mobile at fault for storing my voicemeil&lt;/a&gt;? 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.&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;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 &lt;i&gt;am&lt;/i&gt; 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.&amp;nbsp;&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;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.)&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;Think about that for a minute: an entire company put on hold on the basis of an &lt;i&gt;allegation&lt;/i&gt;&amp;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.&amp;nbsp;&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;Replace "T-Mobile" with "YouTube," "Facebook," or "Google" and that's SOPA.&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;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 &lt;i&gt;solid proof&lt;/i&gt;&amp;nbsp;that they are &lt;i&gt;killing people&lt;/i&gt;. 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 &lt;i&gt;alleged&lt;/i&gt;&amp;nbsp;that that one of that company's &lt;i&gt;customers&lt;/i&gt;&amp;nbsp;did something that &lt;i&gt;might&lt;/i&gt;&amp;nbsp;be wrong.&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;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."&lt;/span&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;br style="background-color: white; color: #333333; line-height: 18px;" /&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;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?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: white; color: #333333; line-height: 18px;"&gt;So please, contact your congressperson. Wikipedia has a &lt;a href="http://en.wikipedia.org/wiki/Special:CongressLookup"&gt;search tool&lt;/a&gt;&amp;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.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-8151892683652770886?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/8151892683652770886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2012/01/darkness-on-internet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/8151892683652770886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/8151892683652770886'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2012/01/darkness-on-internet.html' title='Darkness on the Internet'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-6636042049707273786</id><published>2011-11-28T13:38:00.001-08:00</published><updated>2011-11-28T13:43:08.580-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>My first "official" Android Blog post...</title><content type='html'>...went live last week &lt;a href="http://android-developers.blogspot.com/2011/11/making-android-games-that-play-nice.html"&gt;here&lt;/a&gt;! 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.&lt;br /&gt;&lt;br /&gt;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. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-6636042049707273786?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/6636042049707273786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/11/my-first-official-android-blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6636042049707273786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6636042049707273786'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/11/my-first-official-android-blog-post.html' title='My first &quot;official&quot; Android Blog post...'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-9202140772660440858</id><published>2011-09-19T12:13:00.000-07:00</published><updated>2011-09-19T12:55:50.073-07:00</updated><title type='text'>Bug in LockFreePipe</title><content type='html'>Dmitry 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 &lt;a href="http://dx9-occlusion-sample.googlecode.com/svn-history/r43/trunk/DXUT/Optional/DXUTLockFreePipe.h"&gt;here&lt;/a&gt;. 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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="white-space: pre-wrap; word-wrap: break-word;"&gt;        unsigned long cbTailBytes = min( bytesLeft, c_cbBufferSize - actualReadOffset );&lt;br /&gt;#ifdef _XBOX_VER&lt;br /&gt;        XMemCpy( pbDest, m_pbBuffer + actualReadOffset, cbTailBytes );&lt;br /&gt;#else&lt;br /&gt;        memcpy( pbDest, m_pbBuffer + actualReadOffset, cbTailBytes );&lt;br /&gt;#endif&lt;br /&gt;        bytesLeft -= cbTailBytes;&lt;br /&gt;&lt;br /&gt;        if( bytesLeft )&lt;br /&gt;        {&lt;br /&gt;#ifdef _XBOX_VER&lt;br /&gt;            XMemCpy( pbDest + cbTailBytes, m_pbBuffer, bytesLeft );&lt;br /&gt;#else&lt;br /&gt;            memcpy( pbDest + cbTailBytes, m_pbBuffer, bytesLeft );&lt;br /&gt;#endif&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;// OOPS: no barrier here. These operations could be reordered&lt;/span&gt;&lt;/pre&gt;&lt;pre style="white-space: pre-wrap; word-wrap: break-word;"&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;// by the compiler or by the CPU. Should have lwsync or _ReadWriteBarrier here.&lt;/span&gt;&lt;br /&gt;        readOffset += cbDest;&lt;br /&gt;        m_readOffset = readOffset;&lt;/pre&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="white-space: pre-wrap; word-wrap: break-word;"&gt;   bool __forceinline          Write( const void* pvSrc, unsigned long cbSrc )&lt;br /&gt;    {&lt;br /&gt;        // Reading the read offset here has the same caveats as reading&lt;br /&gt;        // the write offset had in the Read() function above. &lt;br /&gt;        DWORD readOffset = m_readOffset;&lt;/pre&gt;&lt;pre style="white-space: pre-wrap; word-wrap: break-word;"&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;// OOPS: need lwsync or _ReadWriteBarrier here if we want it to work&lt;/span&gt;&lt;br /&gt;        DWORD writeOffset = m_writeOffset;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;any&lt;/i&gt;&amp;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?&lt;br /&gt;&lt;br /&gt;I'd say we got lucky. Just because the CPU &lt;i&gt;can&lt;/i&gt;&amp;nbsp;reorder stores before reads, doesn't mean that it &lt;i&gt;does&lt;/i&gt;. 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.&lt;br /&gt;&lt;br /&gt;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 &amp;nbsp;as well as it did because of quirks in the 360's CPU architecture. It's not a generic piece of code.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-9202140772660440858?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/9202140772660440858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/09/bug-in-lockfreepipe.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/9202140772660440858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/9202140772660440858'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/09/bug-in-lockfreepipe.html' title='Bug in LockFreePipe'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-6981651870375233695</id><published>2011-09-10T17:35:00.001-07:00</published><updated>2011-09-10T17:35:45.200-07:00</updated><title type='text'>My current frustration</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;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;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/-N8PYB9uJhNc/TmwCP_9CEKI/AAAAAAAAAHw/GvaqJ-om45g/s320/java+generics.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-6981651870375233695?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/6981651870375233695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/09/my-current-frustration.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6981651870375233695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6981651870375233695'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/09/my-current-frustration.html' title='My current frustration'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-N8PYB9uJhNc/TmwCP_9CEKI/AAAAAAAAAHw/GvaqJ-om45g/s72-c/java+generics.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-7883734871423970604</id><published>2011-09-06T14:00:00.000-07:00</published><updated>2011-09-06T14:00:03.137-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><category scheme='http://www.blogger.com/atom/ns#' term='gtasks'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Checking In...</title><content type='html'>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).&lt;br /&gt;&lt;br /&gt;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.)&lt;br /&gt;&lt;br /&gt;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...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-7883734871423970604?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/7883734871423970604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/09/checking-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/7883734871423970604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/7883734871423970604'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/09/checking-in.html' title='Checking In...'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-651751450423378235</id><published>2011-08-08T15:00:00.000-07:00</published><updated>2011-12-01T15:07:31.586-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='service'/><category scheme='http://www.blogger.com/atom/ns#' term='debugger'/><category scheme='http://www.blogger.com/atom/ns#' term='ndk'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Ndk-gdb and service processes don't (currently) mix</title><content type='html'>&lt;div&gt;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):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="m"&gt;&amp;lt;&lt;/span&gt;&lt;span class="t"&gt;service&lt;/span&gt; &lt;span class="t"&gt;android:name&lt;/span&gt;&lt;span class="m"&gt;="&lt;/span&gt;&lt;b&gt;com.somemiddleware.SomeUsefulService&lt;/b&gt;&lt;span class="m"&gt;"&lt;/span&gt;&lt;span class="t"&gt; android:process&lt;/span&gt;&lt;span class="m"&gt;="&lt;/span&gt;&lt;b&gt;:com.somemiddleware.useful.process&lt;/b&gt;&lt;span class="m"&gt;"&lt;/span&gt;&lt;span class="m"&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;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 &lt;i&gt;always&lt;/i&gt;&amp;nbsp;work.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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&amp;nbsp;"com.mycompany.mygame:com.somemiddleware.useful.process" -- and guess which one gets matched by the ndk-gdb awk script?&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you're interested, here's a gnu diff version of the patch:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;25,27d24&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt; # NOTE: For some reason, simply using $9 == PACKAGE does not work&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt; # &amp;nbsp; &amp;nbsp; &amp;nbsp; with this script, so use pattern matching instead.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt; #&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;31a29&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; &amp;nbsp; &amp;nbsp; RS = "\r\n"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;40c38&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt; &amp;nbsp; &amp;nbsp; gsub("\\.","\\.",PACKAGE)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; &amp;nbsp; &amp;nbsp; #gsub("\\.","\\.",PACKAGE)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;46c44&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt; $9 ~ PACKAGE {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt; $9 == PACKAGE {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-651751450423378235?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/651751450423378235/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/08/ndk-gdb-and-service-processes-dont.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/651751450423378235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/651751450423378235'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/08/ndk-gdb-and-service-processes-dont.html' title='Ndk-gdb and service processes don&apos;t (currently) mix'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-5719092491115730225</id><published>2011-07-12T11:33:00.000-07:00</published><updated>2011-07-12T11:33:56.278-07:00</updated><title type='text'>Yes, I am now on Google+</title><content type='html'>&lt;a href="https://plus.google.com/109486821799932251955/posts"&gt;Of course.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-5719092491115730225?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/5719092491115730225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/07/yes-i-am-now-on-google.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/5719092491115730225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/5719092491115730225'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/07/yes-i-am-now-on-google.html' title='Yes, I am now on Google+'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-3148321246459689799</id><published>2011-07-08T10:38:00.000-07:00</published><updated>2011-07-08T10:38:37.106-07:00</updated><title type='text'>Anyone want to do some Android ports?</title><content type='html'>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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-3148321246459689799?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/3148321246459689799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/07/anyone-want-to-do-some-android-ports.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/3148321246459689799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/3148321246459689799'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/07/anyone-want-to-do-some-android-ports.html' title='Anyone want to do some Android ports?'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-1617303186913592223</id><published>2011-05-27T08:36:00.000-07:00</published><updated>2011-09-06T13:49:14.354-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='ndk'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>I'm slowly learning to hate Eclipse less</title><content type='html'>I'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.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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. &lt;a href="http://twitter.com/#!/fredsa"&gt;Fred Sauer&lt;/a&gt;, better known as one of the minds behind &lt;a href="https://chrome.google.com/webstore/detail/aknpkdffaafgjchaibgeefbgmgeghloj?utm_campaign=en&amp;amp;utm_source=ha-en-na-us-webapp-angrybirds&amp;amp;utm_medium=ha"&gt;Angry Birds Chrome&lt;/a&gt;, 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:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;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.&lt;/li&gt;&lt;li&gt;"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!&lt;/li&gt;&lt;li&gt;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....&lt;/li&gt;&lt;li&gt;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.&lt;/li&gt;&lt;li&gt;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.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;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.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-1617303186913592223?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/1617303186913592223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/05/im-slowly-learning-to-hate-eclipse-less.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1617303186913592223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1617303186913592223'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/05/im-slowly-learning-to-hate-eclipse-less.html' title='I&apos;m slowly learning to hate Eclipse less'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-5254341102859704292</id><published>2011-05-18T22:03:00.000-07:00</published><updated>2011-12-01T15:06:18.885-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='debugger'/><category scheme='http://www.blogger.com/atom/ns#' term='ndk'/><category scheme='http://www.blogger.com/atom/ns#' term='run-as'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><category scheme='http://www.blogger.com/atom/ns#' term='root'/><title type='text'>NDK debugging without root access</title><content type='html'>&lt;a href="http://ian-ni-lewis.blogspot.com/2011/05/victory.html"&gt;Recently&lt;/a&gt;&amp;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 (&lt;i&gt;cough, OpenGL 2, cough&lt;/i&gt;) 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?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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&amp;nbsp;&lt;a href="http://xkcd.com/149/"&gt;sudo&lt;/a&gt;-style&amp;nbsp;temporary privilege escalation, which while sometimes &lt;a href="http://en.wikipedia.org/wiki/File:Windows_7_UAC.png"&gt;annoying&lt;/a&gt;, at least prevents everyone from&lt;a href="http://en.wikipedia.org/wiki/Windows_XP"&gt; running as root all the time&lt;/a&gt;). 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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645"&gt;ProcMon &lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt;adb shell&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;/data/data/com.example.testwingdb/lib/gdbserver :1001 --attach 1221&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;Cannot attach to process 1221: Operation not permitted (1)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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. [&lt;b&gt;Edited to add&lt;/b&gt;: Some Android device builds have issues with run-as. See my comment (comment #3 below this post).]&lt;br /&gt;&lt;br /&gt;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.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt;adb shell id&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;uid=2000(shell) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1009&lt;/b&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;(mount),1011(adb),1015(sdcard_rw),3001(net_bt_admin),3002(net_bt),3003(inet)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt;adb shell run-as com.example.testwingdb id&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;uid=10117(app_117) gid=10117(app_117) groups=1003(graphics),1004(input),1007(log&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;),1009(mount),1011(adb),1015(sdcard_rw),3001(net_bt_admin),3002(net_bt),3003(ine&lt;/b&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;t)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So we use run-as and all is dandy, right? Not quite yet.&amp;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.&lt;br /&gt;&lt;br /&gt;With this in mind, we can make a very small tweak to the command line:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt;adb shell run-as com.example.testwingdb /data/da&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ta/com.example.testwingdb/lib/gdbserver :1001 --attach 1221&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;Attached; pid = 1221&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Woohoo!! Gdbserver is launched and has successfully attached to my process. All is perfect.... well, until this happens:&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;Can't bind address: Permission denied.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;Exiting&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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&amp;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:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt;adb forward tcp:5039 localfilesystem:/data/data/com.example.testwingdb/debug-pipe&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To use the named pipe, we launch gdbserver like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;gt;adb shell run-as com.example.testwingdb /data/da&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ta/com.example.testwingdb/lib/gdbserver +debug-pipe --attach 1221&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Attached; pid = 1221&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Listening on sockaddr socket debug-socket&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;As far as I can tell, that's all it takes to enable rootless debugging. Let's review:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Launch gdbserver under the uid of the process to be debugged, using run-as.&lt;/li&gt;&lt;li&gt;Tell gdbserver to use a named pipe instead of a socket to communicate with the host.&lt;/li&gt;&lt;li&gt;Use adb forward to forward the device-side named pipe to a host-side tcp socket.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Hope that helps!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-5254341102859704292?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/5254341102859704292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/05/ndk-debugging-without-root-access.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/5254341102859704292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/5254341102859704292'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/05/ndk-debugging-without-root-access.html' title='NDK debugging without root access'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-984477115664177385</id><published>2011-05-16T22:46:00.000-07:00</published><updated>2011-09-06T13:49:25.396-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GDC'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Android talks from GDC...</title><content type='html'>...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:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;My talk, &lt;a href="http://www.youtube.com/watch?v=5yorhsSPFG4"&gt;Bringing C and C++ Games to Android&lt;/a&gt;, 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.&lt;/li&gt;&lt;li&gt;Dan's other talk, &lt;a href="http://www.youtube.com/watch?v=TnSNCXR9fbY"&gt;Evading Pirates and Stopping Vampires&lt;/a&gt;, 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.&lt;/li&gt;&lt;li&gt;Nico Weber's &lt;a href="http://www.youtube.com/watch?v=YLVbLVtjDDw"&gt;3D Graphics on Android: Lessons Learned from Google Body&lt;/a&gt;. 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.&lt;/li&gt;&lt;li&gt;And the great Chris Pruett, no longer a Googler but still passionate about Android gaming, reprised his excellent presentation &lt;a href="http://www.youtube.com/watch?v=cdvaPyq_eBU"&gt;Building Aggressively Compatible Android Games&lt;/a&gt;. Check out Chris's new venture, &lt;a href="http://robotinvader.com/blog/"&gt;Robot Invader&lt;/a&gt;. He's already got a better blog than mine, so go over there and read his stuff now.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;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.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-984477115664177385?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/984477115664177385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/05/android-talks-from-gdc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/984477115664177385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/984477115664177385'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/05/android-talks-from-gdc.html' title='Android talks from GDC...'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-1746354704622899611</id><published>2011-05-16T22:09:00.000-07:00</published><updated>2011-05-16T22:09:39.655-07:00</updated><title type='text'>Victory!</title><content type='html'>I finally got the latest version of &lt;a href="http://www.wingdb.com/wgMobileEdition.htm"&gt;WinGDB For Android&lt;/a&gt; to really truly work. Best news: it's faster than the Eclipse debugger. A &lt;i&gt;lot&lt;/i&gt;&amp;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.&lt;br /&gt;&lt;br /&gt;Just a few small snags in what is, after all, still a beta product:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;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.&lt;/li&gt;&lt;li&gt;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. &lt;a href="http://code.google.com/p/nativeclient-vsx/"&gt;Even a debugger replacement&lt;/a&gt;.&amp;nbsp;&lt;/li&gt;&lt;li&gt;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.&lt;/li&gt;&lt;li&gt;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.&amp;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.&lt;/li&gt;&lt;li&gt;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 &lt;i&gt;everything&lt;/i&gt;. 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.&lt;/li&gt;&lt;li&gt;And a smattering of small UI bugs that you'd expect from a beta build.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;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.&amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-1746354704622899611?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/1746354704622899611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/05/victory.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1746354704622899611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1746354704622899611'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/05/victory.html' title='Victory!'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-3722278529378791790</id><published>2011-04-27T12:04:00.000-07:00</published><updated>2011-04-27T12:04:34.619-07:00</updated><title type='text'>Big life changes!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;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;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/-CUk1ZmrIu2w/Tbg-CS2sz-I/AAAAAAAAADI/NHRe3ndOrOM/s320/IMG_20110425_221147.jpg" width="301" /&gt;&lt;/a&gt;&lt;/div&gt;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.&lt;br /&gt;&lt;br /&gt;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.&amp;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.&lt;br /&gt;&lt;br /&gt;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. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-3722278529378791790?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/3722278529378791790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/04/big-life-changes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/3722278529378791790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/3722278529378791790'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/04/big-life-changes.html' title='Big life changes!'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-CUk1ZmrIu2w/Tbg-CS2sz-I/AAAAAAAAADI/NHRe3ndOrOM/s72-c/IMG_20110425_221147.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-5936588734061503159</id><published>2011-03-28T13:34:00.000-07:00</published><updated>2011-05-16T23:46:35.557-07:00</updated><title type='text'>GDC slides, how do they work?</title><content type='html'>[update: (versions of) (most of) these talks are &lt;a href="http://ian-ni-lewis.blogspot.com/2011/05/android-talks-from-gdc.html"&gt;now online&lt;/a&gt;!]&lt;br /&gt;&lt;br /&gt;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? "&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.)&lt;br /&gt;&lt;br /&gt;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. &lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-5936588734061503159?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/5936588734061503159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/gdc-slides-how-do-they-work.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/5936588734061503159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/5936588734061503159'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/gdc-slides-how-do-they-work.html' title='GDC slides, how do they work?'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-6298449965089748975</id><published>2011-03-24T10:18:00.000-07:00</published><updated>2011-03-24T10:20:24.286-07:00</updated><title type='text'>Handedness! Argh!</title><content type='html'>This week I started hacking on &lt;a href="http://www.unity3d.com/"&gt;Unity&lt;/a&gt;, 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&amp;nbsp;&lt;a href="http://big1.codeplex.com/"&gt;something&lt;/a&gt;&amp;nbsp;I've been lazily experimenting with since I left &lt;a href="http://en.wikipedia.org/wiki/Offset_Software"&gt;Offset Software&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;were&lt;/i&gt;&amp;nbsp;a real artist. So far I've been able to create a bad copy of the ship from&lt;i&gt;&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Elite_(video_game)"&gt;Elite&lt;/a&gt;&lt;/i&gt;, and that's about it.) And best of all, Unity imports Maya files directly. No exporter FTW!!!.....&lt;br /&gt;&lt;br /&gt;...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 &lt;i&gt;back&lt;/i&gt;&amp;nbsp;of what it's following.)&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Maybe someone reading this knows how to fix the handedness mismatch between Maya and Unity in a clean way?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-6298449965089748975?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/6298449965089748975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/handedness-argh.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6298449965089748975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6298449965089748975'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/handedness-argh.html' title='Handedness! Argh!'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-7311884924178433440</id><published>2011-03-19T19:02:00.000-07:00</published><updated>2011-03-19T19:02:24.566-07:00</updated><title type='text'>So close but yet so far...</title><content type='html'>So WinGDB has a &lt;a href="http://www.wingdb.com/wgMobileEdition.htm"&gt;beta &lt;/a&gt;up of their "mobile edition," which is light years beyond the hacktastic preview I &lt;a href="http://ian-ni-lewis.blogspot.com/2011/01/its-like-coming-home-again.html"&gt;wrote about&lt;/a&gt; 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 &lt;i&gt;gone&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Well, it's probably for the best. I'd promised myself this would be the weekend that I finally learned how to use &lt;a href="http://www.unity3d.com/"&gt;Unity&lt;/a&gt;. So I'll get onto that. Leave a comment if you get the WinGDB beta working better than I did...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-7311884924178433440?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/7311884924178433440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/so-close-but-yet-so-far.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/7311884924178433440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/7311884924178433440'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/so-close-but-yet-so-far.html' title='So close but yet so far...'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-1183083570118943343</id><published>2011-03-19T18:22:00.000-07:00</published><updated>2011-03-19T18:22:26.852-07:00</updated><title type='text'>Weekend Blogging: a recipe hack</title><content type='html'>Three weeks ago I made a soup with Lagunitas &lt;a href="http://beeradvocate.com/beer/profile/220/1579"&gt;GnarlyWine&lt;/a&gt;&amp;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 &lt;a href="http://www.lagunitas.com/beers/hopstoopid.html"&gt;Hop Stoopid&lt;/a&gt;, which did &lt;i&gt;not&lt;/i&gt;&amp;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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.healthytraders.com/stainless-steel-gourmet-automatic-electric-pressure-cooker-p-3220.html"&gt;automatic pressure cooker&lt;/a&gt;.&amp;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.&lt;br /&gt;&lt;br /&gt;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):&lt;br /&gt;&lt;br /&gt;16 oz ribeye steak, cubed&lt;br /&gt;1 lb bag frozen peas &amp;amp; carrots&lt;br /&gt;3 red potatos, also cubed&lt;br /&gt;1 tbsp 10 year old balsamic vinegar&lt;br /&gt;1 tbsp white truffle oil&lt;br /&gt;1/2 tbsp onion powder&lt;br /&gt;1/2 tbsp brown gravy mix&lt;br /&gt;1 tsp garlic Season-All&lt;br /&gt;1 tsp basil&lt;br /&gt;1 tsp oregano&lt;br /&gt;1 tbsp extra-virgin olive oil&lt;br /&gt;&lt;br /&gt;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!&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Oh man, you know what would go awesome with this? A bottle of burgundy. Good thing &lt;i&gt;I'm&lt;/i&gt;&amp;nbsp;not pregnant... :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-1183083570118943343?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/1183083570118943343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/weekend-blogging-recipe-hack.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1183083570118943343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1183083570118943343'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/weekend-blogging-recipe-hack.html' title='Weekend Blogging: a recipe hack'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-2265188316135353013</id><published>2011-03-12T11:02:00.000-08:00</published><updated>2011-03-12T11:02:37.060-08:00</updated><title type='text'>In case you're wondering...</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;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 :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-2265188316135353013?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/2265188316135353013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/in-case-youre-wondering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/2265188316135353013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/2265188316135353013'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/in-case-youre-wondering.html' title='In case you&apos;re wondering...'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-1994671478537033725</id><published>2011-03-02T10:24:00.000-08:00</published><updated>2011-03-08T10:25:46.669-08:00</updated><title type='text'>Another Open Letter</title><content type='html'>An Open Letter to whomever stole my Motorola Xoom tablet at GDC.&lt;br /&gt;&lt;br /&gt;Dear Sir or Madam:&lt;br /&gt;You stole my stuff. You suck.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;:-)&lt;br /&gt;&lt;br /&gt;Ian&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-1994671478537033725?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/1994671478537033725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/another-open-letter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1994671478537033725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1994671478537033725'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/another-open-letter.html' title='Another Open Letter'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-7151231342876005445</id><published>2011-03-01T20:48:00.000-08:00</published><updated>2011-03-01T21:01:59.715-08:00</updated><title type='text'>Letter to a Bike Thief</title><content type='html'>&lt;div class="p1"&gt;An open letter to whomever stole my bike from the rack at the Moscone Center last night.&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;Dear Sir or Madam,&lt;/div&gt;&lt;div class="p1"&gt;First of all, &lt;i&gt;ha ha ha ha ha ha ha&lt;/i&gt;. 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.&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;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.&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;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.&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;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 &lt;i&gt;this close&lt;/i&gt;&amp;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.&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;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.&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;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.&lt;br /&gt;&lt;br /&gt;So enjoy the bike. You're the one that has to live with being a lousy thief.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-7151231342876005445?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/7151231342876005445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/letter-to-bike-thief.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/7151231342876005445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/7151231342876005445'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/letter-to-bike-thief.html' title='Letter to a Bike Thief'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-2781531369862156635</id><published>2011-03-01T20:44:00.000-08:00</published><updated>2011-03-01T20:44:37.798-08:00</updated><title type='text'>GDC: Coming up for air</title><content type='html'>After 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.&amp;nbsp;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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, &amp;nbsp;and introduced things that I've been talking about on this blog, like &lt;a href="http://ian-ni-lewis.blogspot.com/2011/01/its-like-coming-home-again.html"&gt;WinGDB&lt;/a&gt;&amp;nbsp;and &lt;a href="http://vs-android.googlecode.com/"&gt;vs-android&lt;/a&gt;. 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!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So dev days are over, and I'm relieved. There were some gaffes but overall I'm pleased. Thanks much to everyone who attended!&amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-2781531369862156635?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/2781531369862156635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/gdc-coming-up-for-air.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/2781531369862156635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/2781531369862156635'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/03/gdc-coming-up-for-air.html' title='GDC: Coming up for air'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-6354080825088687556</id><published>2011-02-21T18:08:00.000-08:00</published><updated>2011-02-21T18:08:35.072-08:00</updated><title type='text'>One week to go...</title><content type='html'>I learned something today: putting on a show, even just a little corner of a show like &lt;a href="http://google.com/gdc2011"&gt;Google Developer Days at GDC&lt;/a&gt;, is &lt;i&gt;really hard&lt;/i&gt;. 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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-6354080825088687556?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/6354080825088687556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/02/one-week-to-go.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6354080825088687556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6354080825088687556'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/02/one-week-to-go.html' title='One week to go...'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-5868445042946858664</id><published>2011-02-13T18:14:00.000-08:00</published><updated>2011-02-13T18:14:18.676-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GDC'/><title type='text'>GDC</title><content type='html'>If you've been following my twitter feed--or any of my coworkers' feeds--you've probably heard that we launched a &lt;a href="http://www.google.com/events/gdc/2011/"&gt;GDC microsite&lt;/a&gt;&amp;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 &lt;a href="http://www.google.com/tv/"&gt;Google TV site&lt;/a&gt;, 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.&lt;br /&gt;&lt;br /&gt;If you haven't already, this would be a good time to check out google.com/gdc2011. Especially check out the &lt;a href="http://www.google.com/events/gdc/2011/speakers.html"&gt;speaker bios&lt;/a&gt;--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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-5868445042946858664?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/5868445042946858664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/02/gdc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/5868445042946858664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/5868445042946858664'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/02/gdc.html' title='GDC'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-2042981874472842254</id><published>2011-01-26T20:14:00.000-08:00</published><updated>2011-01-26T20:15:26.413-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android NDK file IStream stream makefiles build'/><title type='text'>In which I access a file</title><content type='html'>Hola 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....&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://twitter.com/#!/dagalpin"&gt;Dan Galpin&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Use the asset manager code to get an AssetFileDescriptor:&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;AssetFileDescriptor afd =&lt;/span&gt;&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;context.getAssets().openFd("ToothyDroid.png")&lt;/span&gt;;&lt;/blockquote&gt;&lt;blockquote&gt;Read the offset and length from the AssetFileDescriptor:&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;long offset = afd.getStartOffset();&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;long length = afd.getDeclaredLength();&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;afd.close();&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;Get the APK file name:&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;context.getApplicationInfo().sourceDir;&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;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? ;-)]&lt;/blockquote&gt;&lt;br /&gt;Yeah. Weird.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 11px;"&gt;&lt;span class="whitespace"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="text"&gt;AAsset* pAsset = AAssetManager_open(ctx-&amp;gt;app-&amp;gt;activity-&amp;gt;assetManager, "readme.txt", AASSET_MODE_UNKNOWN);&lt;/span&gt;&lt;br /&gt;&lt;span class="whitespace"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="whitespace"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="text"&gt;const int count = 80;&lt;/span&gt;&lt;br /&gt;&lt;span class="whitespace"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="text"&gt;char buf[count + 1] = {0};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="whitespace"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="text"&gt;while (AAsset_read(pAsset, buf, count) &amp;gt; 0) {&lt;/span&gt;&lt;br /&gt;&lt;span class="whitespace"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="text"&gt;LOGI(buf);&lt;/span&gt;&lt;br /&gt;&lt;span class="whitespace"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="text"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="whitespace"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class="text"&gt;AAsset_close(pAsset);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;That's better, right? It at least feels something like a normal set of filesystem calls. Rock on!!&lt;br /&gt;&lt;br /&gt;Of course, it &lt;i&gt;isn't&lt;/i&gt;&amp;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul class="ul1"&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-2042981874472842254?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/2042981874472842254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/in-which-i-access-file.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/2042981874472842254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/2042981874472842254'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/in-which-i-access-file.html' title='In which I access a file'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-4049869450378322536</id><published>2011-01-18T13:29:00.000-08:00</published><updated>2011-01-18T13:29:23.125-08:00</updated><title type='text'>Interview with TechWeb</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://www.jointhegamenetwork.com/img/site/logo_ubmTW.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://www.jointhegamenetwork.com/img/site/logo_ubmTW.png" /&gt;&lt;/a&gt;&lt;/div&gt;UBM Game Network newsletter did an interview with me as part of their pre-GDC coverage. You can read the interview &lt;a href="http://www.jointhegamenetwork.com/thismonth/011711.html?cid=JTGNN_011711#2"&gt;here&lt;/a&gt;. 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.&amp;nbsp;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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 &lt;i&gt;pretend&lt;/i&gt;&amp;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.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-4049869450378322536?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/4049869450378322536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/interview-with-techweb.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/4049869450378322536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/4049869450378322536'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/interview-with-techweb.html' title='Interview with TechWeb'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-711883360892644640</id><published>2011-01-11T14:38:00.000-08:00</published><updated>2011-07-15T12:12:23.929-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='visual studio'/><category scheme='http://www.blogger.com/atom/ns#' term='ndk'/><category scheme='http://www.blogger.com/atom/ns#' term='debugging'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Android Debugging, Visual Studio style!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;UPDATE: &lt;/b&gt;More recent beta versions of wingdb make these instructions obsolete. Try it &lt;a href="http://www.wingdb.com/wgMobileEdition.htm"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The high point of my week, courtesy of the good people at www.wingdb.com... (click to enlarge)&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_sqY98z7AHIM/TSzaXF1pYsI/AAAAAAAAAB4/ryvJavX05L8/s1600/Android-msvs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="352" src="http://3.bp.blogspot.com/_sqY98z7AHIM/TSzaXF1pYsI/AAAAAAAAAB4/ryvJavX05L8/s400/Android-msvs.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Full Android NDK debugging in Visual Studio. This is using version 1.8, which is kind of tricky to set up--mad props to the WinGDB support folks who walked me through it. Version 2.0 is coming soon, though, and according to WinGDB, they will have full support for Android NDK.&lt;br /&gt;&lt;br /&gt;For the curious, here's how I got this working. &amp;nbsp;If you want to try this, do so at your own risk and &lt;b&gt;please&lt;/b&gt;&amp;nbsp;don't go bugging the WinGDB folks about it; they're busy enough working on version 2.0 and they don't need anything slowing them down! For this example, I'm using the project I described in an &lt;a href="http://ian-ni-lewis.blogspot.com/2011/01/adventures-on-android-ndk-part-i.html"&gt;earlier post&lt;/a&gt;.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;First, install all of the normal prerequisites--Cygwin, Android SDK, and Android NDK. I'm using the latest Android stuff, which as of now is SDK tools r8 and NDK r5. Install Visual Studio and WinGDB as well. Run "android.bat" and make sure everything is up to date. You might also want to set the environment variables ANDROID_SDK and ANDROID_NDK to point to the root of the SDK and NDK, respectively.&lt;/li&gt;&lt;li&gt;Since the current WinGDB build was based on the previous SDK, you'll need to copy adb.exe back to where it used to be in the old SDK:&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;copy %ANDROID_SDK%\platform-tools\adb.exe %ANDROID_SDK%\tools&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Create an NDK project (or use one of the samples). Build the project using ndk-build. Then, run &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ndk-gdb --start&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;. This will set up the files that gdb needs to see in order for WinGDB to attach. As soon as the gdb prompt appears, type &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;quit &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;to dismiss it. Elsewhere in these instructions I'll assume that the environment variable PROJECT_ROOT points to the root directory of your project (where AndroidManifest.xml lives).&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Regedit time! You need to add an entry for "AndroidSDKPath" to WinGDB/Preferences/General. The exact location of this key will vary depending on your OS. I have 64-bit Windows7 so mine shows up under HKLM/SOFTWARE/Wow6432Node. YMMV. In any case, the value for AndroidSDKPath should be the full path to wherever you installed the Android SDK, like so:&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_sqY98z7AHIM/TS4y2hFlqCI/AAAAAAAAAB8/d7JyItF-Yqk/s1600/wingdb-registry.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="263" src="http://4.bp.blogspot.com/_sqY98z7AHIM/TS4y2hFlqCI/AAAAAAAAAB8/d7JyItF-Yqk/s400/wingdb-registry.PNG" width="400" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;In Visual Studio, open the WinGDB preferences dialog (choose WinGDB|Preferences... from the main menu). Set the following options:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Default debugger path:&amp;nbsp;&lt;/b&gt;%ANDROID_NDK%\toolchains\arm-eabi-4.4.0\prebuilt\windows\bin\arm-eabi-gdb.exe&lt;/li&gt;&lt;li&gt;&lt;b&gt;Use Cygwin mode for local sessions:&lt;/b&gt; yes&lt;/li&gt;&lt;li&gt;&lt;b&gt;Cygwin installation (root) path:&lt;/b&gt; wherever you installed this (default is c:\cygwin)&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_sqY98z7AHIM/TS41Z6gTgWI/AAAAAAAAACA/MroZGz_Yk1E/s1600/wingdb-prefs.PNG" imageanchor="1" style="clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://4.bp.blogspot.com/_sqY98z7AHIM/TS41Z6gTgWI/AAAAAAAAACA/MroZGz_Yk1E/s400/wingdb-prefs.PNG" width="400" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Dismiss the preferences dialog.&amp;nbsp;&lt;/li&gt;&lt;li&gt;From the Visual Studio main menu, select WinGDB|Attach to process...&lt;/li&gt;&lt;li&gt;Set the following options (you should only need to do this once):&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Target type&lt;/b&gt;: Embedded Linux System (gdbserver)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Executable path:&lt;/b&gt; &amp;lt;path to your project&amp;gt;\obj\local\armeabi\app_process&lt;/li&gt;&lt;li&gt;&lt;b&gt;Target login:&lt;/b&gt; &amp;lt;your device id&amp;gt;:adb (or emulator:adb if you're using the emulator)&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_sqY98z7AHIM/TS43knAo5XI/AAAAAAAAACE/bacFNYyO0Bw/s1600/wingdb-attach.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="221" src="http://4.bp.blogspot.com/_sqY98z7AHIM/TS43knAo5XI/AAAAAAAAACE/bacFNYyO0Bw/s400/wingdb-attach.PNG" width="400" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Press the "Advanced Settings..." button. In the Advanced Settings dialog, set the following options:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;Environment tab&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Debugger path:&lt;/b&gt;&amp;nbsp;%ANDROID_NDK%\toolchains\arm-eabi-4.4.0\prebuilt\windows\bin\arm-eabi-gdb.exe&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_sqY98z7AHIM/TS45FcAgEDI/AAAAAAAAACM/lutk8XwjCnQ/s1600/wingdb-advanced-env.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="282" src="http://3.bp.blogspot.com/_sqY98z7AHIM/TS45FcAgEDI/AAAAAAAAACM/lutk8XwjCnQ/s400/wingdb-advanced-env.PNG" width="400" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Directories tab&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Additional source directories:&lt;/b&gt;&amp;nbsp;%ANDROID_NDK%\platforms\android-9\arch-arm&lt;/li&gt;&lt;li&gt;&lt;b&gt;Shared library directories:&lt;/b&gt;&amp;nbsp;%ANDROID_NDK%\platforms\android-9\arch-arm\usr\lib;%PROJECT_ROOT%\obj\local\armeabi&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_sqY98z7AHIM/TS45FHoDPvI/AAAAAAAAACI/TAYEhJ7biWs/s1600/wingdb-advanced-dirs.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="282" src="http://1.bp.blogspot.com/_sqY98z7AHIM/TS45FHoDPvI/AAAAAAAAACI/TAYEhJ7biWs/s400/wingdb-advanced-dirs.PNG" width="400" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Target tab&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Sysroot on host:&lt;/b&gt;&amp;nbsp;/cygdrive/c/sdk/android-ndk-r5/platforms/android-9/arch-arm (notice that this has to be in Cygwin path format, so I can't use %ANDROID_NDK%. In this case my ndk is installed under c:\sdk\android-ndk-r5, which in Cygwin turns into /cygdrive/c/sdk/android-ndk-r5. You'll need to change that to whatever your local NDK path is in Cygwinese.)&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_sqY98z7AHIM/TS45GDLrYgI/AAAAAAAAACU/Wiz5B1oYMTw/s1600/wingdb-advanced-target.PNG" imageanchor="1"&gt;&lt;img border="0" height="283" src="http://1.bp.blogspot.com/_sqY98z7AHIM/TS45GDLrYgI/AAAAAAAAACU/Wiz5B1oYMTw/s400/wingdb-advanced-target.PNG" width="400" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Server tab&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Launch server from sysroot:&lt;/b&gt; no&lt;/li&gt;&lt;li&gt;&lt;b&gt;Path to gdbserver:&lt;/b&gt; /system/bin/gdbserver&lt;/li&gt;&lt;li&gt;&lt;b&gt;Server port:&lt;/b&gt; an unused IP port (I used 1100)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Server port is forwarded:&lt;/b&gt; yes&lt;/li&gt;&lt;li&gt;&lt;b&gt;Forwarded server port:&lt;/b&gt; another unused port (in my case, 11000).&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_sqY98z7AHIM/TS45F37Z9zI/AAAAAAAAACQ/MQW-uLsEWkQ/s1600/wingdb-advanced-server.PNG" imageanchor="1"&gt;&lt;img border="0" height="282" src="http://4.bp.blogspot.com/_sqY98z7AHIM/TS45F37Z9zI/AAAAAAAAACQ/MQW-uLsEWkQ/s640/wingdb-advanced-server.PNG" width="400" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;li&gt;Check "Save these settings as project defaults" unless you enjoy typing them in over and over again. (Yeah, I learned that the hard way.)&lt;/li&gt;&lt;li&gt;Dismiss the Advanced Settings dialog.&lt;/li&gt;&lt;li&gt;Back in the Attach to remote process dialog, check "Show processes from all users."&lt;/li&gt;&lt;li&gt;If you don't see any processes, click Refresh. You should see a long list of processes that are running on your device or emulator. User processes are listed by package name, so search for your package name and select it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_sqY98z7AHIM/TS49ZVdhmXI/AAAAAAAAACY/dJPcNEMOzcI/s1600/wingdb-attach-2.PNG" imageanchor="1"&gt;&lt;img border="0" height="231" src="http://4.bp.blogspot.com/_sqY98z7AHIM/TS49ZVdhmXI/AAAAAAAAACY/dJPcNEMOzcI/s400/wingdb-attach-2.PNG" width="400" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Click the Attach button and wait a bit&lt;/li&gt;&lt;li&gt;You'll see a message box warning you that there are no debug symbols in the executable. Dismiss it. It's true that the executable on the device doesn't have symbols that WinGDb can use; that's why you set up the shared libraries directory back in step 9.2.&lt;/li&gt;&lt;li&gt;Set a breakpoint and enjoy!&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;To debug again, just repeat from step 12. You'll only need to fiddle with the settings again if you switch to a new project, in which case you'll probably need to adjust the paths that are relative to your project root.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As far as I can tell, WinGDB works pretty well. I was able to set breakpoints, step through code, and use the watch window. There are limitations, of course; I was only able to attach to processes, not launch them, and the "autos" window didn't work, for instance. But just having the ability to debug in my favorite environment... that made my week.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Just a reminder, what I've described in this post is not a supported use of WinGDB 1.8! Don't go emailing WinGDB asking them to fix things they don't officially support; that's just not cool. (If you do have problems, though, leave a comment here--I can't promise to solve it, but I or some other reader may be able to.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Good luck and let me know if you find this useful.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-711883360892644640?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/711883360892644640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/its-like-coming-home-again.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/711883360892644640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/711883360892644640'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/its-like-coming-home-again.html' title='Android Debugging, Visual Studio style!'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_sqY98z7AHIM/TSzaXF1pYsI/AAAAAAAAAB4/ryvJavX05L8/s72-c/Android-msvs.png' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-3107599819171825985</id><published>2011-01-09T18:17:00.000-08:00</published><updated>2011-01-12T16:40:57.855-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='visual studio'/><category scheme='http://www.blogger.com/atom/ns#' term='ndk'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Adventures on Android NDK, Part II: Some useful tools</title><content type='html'>Finally got some more time to play around with the NDK. And yes, I'm still stubbornly in Visual Studio. Here's what I'm using to make my life easier:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.wholetomato.com/"&gt;Visual Assist&lt;/a&gt; (of course!)&lt;/li&gt;&lt;li&gt;&lt;a href="http://nshader.codeplex.com/"&gt;NShader &lt;/a&gt;for GLSL syntax highlighting&lt;/li&gt;&lt;li&gt;&lt;a href="http://gnuwin32.sourceforge.net/"&gt;GnuWin32 &lt;/a&gt;so I can take advantage of tools like "which" and "sed" without having to go full Cygwin. (I never go full Cygwin if I can help it.)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.wingdb.com/"&gt;WinGDB &lt;/a&gt;which almost, any day now, will support native Android debugging.... I'm counting the days!&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;I also upgraded to VS2010. Jury's still out on whether that's an improvement. They moved some stuff around and made it purple.&amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-3107599819171825985?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/3107599819171825985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/adventures-on-android-ndk-part-ii-some.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/3107599819171825985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/3107599819171825985'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/adventures-on-android-ndk-part-ii-some.html' title='Adventures on Android NDK, Part II: Some useful tools'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-6666335514499378380</id><published>2011-01-06T19:28:00.000-08:00</published><updated>2011-01-06T19:28:55.573-08:00</updated><title type='text'>Quick Tip: Per-Project Environment Scripts</title><content type='html'>Setting up build scripts for my &lt;a href="http://ian-ni-lewis.blogspot.com/2011/01/adventures-on-android-ndk-part-i.html"&gt;Android exploration&lt;/a&gt;&amp;nbsp;reminded me of something that I learned a while back on the Xbox 360 XDK: scripts that set up a project environment for you. I don't know if this is common knowledge generally--it's a pretty simple idea--but I don't see a lot of game developers doing it, so it seems like it's worth sharing.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The idea behind per-project environment scripts is to create a set of environment variables that describe all of the paths and settings and such for one project. Why would you want to do this? Well, for a simple project it's probably not important. For a project the size of the XDK, though, it was a lifesaver. The determining factor isn't really project size, though. It's the number of permutations you have to deal with. On the XDK, I usually had to deal with four or five completely different build environments:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;My top-of-tree development branch&lt;/li&gt;&lt;li&gt;The current release candidate branch&lt;/li&gt;&lt;li&gt;The last released branch&lt;/li&gt;&lt;li&gt;A retail install of the XDK toolchain&lt;/li&gt;&lt;li&gt;A build of DirectX, where we shared some code from the XDK (and thus had to sanity-check every change we made to make sure we hadn't broken DX).&lt;/li&gt;&lt;li&gt;A (possibly modified) copy of the XDK that the game I was currently debugging had built against&lt;/li&gt;&lt;li&gt;All of the above, replicated on my laptop and on my machine at home.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;To that set of permutations, add all of the different per-user and machine-specific settings you have in a large engineering team. It gets out of hand pretty quickly.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;IDEs like Visual Studio have some features to deal with build and environment permutations, but in my experience they're fragile and hard to discover. In any case, the solution I'm going to talk about here works fine with Visual Studio, as long as you launch devenv.exe from a command line after running the per-project script (or, more likely, invoke devenv.exe from the script itself).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The solution that the XDK used, which I've rewritten and refined a bit to suit my own needs, was really elegant. At the root of each project tree is a shell script named something short and easy like "go.cmd." The script starts* with the most important magic scripting incantation you will ever need to know: the shell script command that remembers the path to the script itself.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;SET PROJECT_ROOT=%~dp0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;or, in the much less cryptic bash lingo:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; white-space: pre-wrap;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;export PROJECT_ROOT=`dirname $0`&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Either command sets &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PROJECT_ROOT&lt;/span&gt; to the directory where the script lives. It doesn't matter where you called the script from, or where the current directory is--&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PROJECT_ROOT&lt;/span&gt; is dependent only on the location of the script. This is what makes the magic happen. It lets you have multiple copies of the same script on your local filesystem, each of which does a subtly different job. Each copy of the script sets up essentially the same environment, but it sets it up relative to its own project root.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After that first magic line, the script settles down to setting all of the variables that are dependent on &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PROJECT_ROOT&lt;/span&gt;, like &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;INCLUDE&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;BINDIR&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;OUTDIR&lt;/span&gt; (or whatever you call the place where object files and executables land in your project). Pretty mundane stuff. This is also a pretty good place to set up values that are shared between all of the solutions in your project--you can use IDE features like Visual Studio solution variables for this, too, but this way seems simpler and easier to me. YMMV.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After the project setup there's one more bit of cleverness:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;call %PROJECT_ROOT%\Users\%USERNAME%\setup_environment.cmd&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The script calls a per-user override file. This is a script that lives in the user's directory under the project root, and calling it gives the user the chance to add their own specific environment variables or what have you. (Notice, by the way, that it has a longer and more descriptive name than "go.cmd." That's because nobody calls this directly, so its name can be as unwieldy as you want.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Wait, back up a minute: Per-user directories? Yeah, here's the deal with that: Somewhere under the project root, in source control, you make a directory called "users." In that directory there's a directory for each user that works on the project. This might seem a little weird if you haven't worked on a project that's structured like this before, but there are two great reasons for doing this:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;It gives everyone a place where they can store version-controlled junk that nobody else wants to see. For instance, I used it to store test data for features that weren't ready yet. Since everyone unmaps all of the users/ directory except for their own subdirectory, it gives you a way to keep things in the repository without pissing off all of your teammates.&lt;/li&gt;&lt;li&gt;It lets you add the per-user configuration scripts that we just talked about. And that lets each user set up their own, possibly temporary, environment: special #defines, filesystem mappings, command aliases, or what have you.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;This idea isn't limited to just users, either. On a couple of projects I worked on I've also called a per-computer script, so that I could have different configurations on my office, laptop, and home machine. On one project I also built in a per-branch config, which seemed helpful at the time. A little crazy, yes, but so what? As long as you check to see whether a script exists before you call it, you can loop in any number of per-whatever config scripts without actually requiring everyone to write the things.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The last thing you do, if you're so inclined, is to launch whatever IDE you're working with. I don't, personally--I think every project should build from the command line, whether or not there's also an IDE involved. But that's just me.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And that's it. Very simple idea, you can set it up in an hour, but it's very powerful. It makes it trivial to manage multiple projects, and multiple versions of each project. And it eliminates the need for every new team member to go and set up their machine environment, and their Visual Studio include paths, and everything else that new team members usually need to set up. Instead, the only thing that a new team member needs to configure is their source control client, because everything else is checked in.**&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;*Well, after the normal stuff like "echo off" and "pushd" and such.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;**Including, if you're really good at this stuff, your entire toolchain. All builds should be 100% reproducible from source.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-6666335514499378380?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/6666335514499378380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/quick-tip-per-project-environment.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6666335514499378380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/6666335514499378380'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/quick-tip-per-project-environment.html' title='Quick Tip: Per-Project Environment Scripts'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-1098535996237175482</id><published>2011-01-03T14:32:00.000-08:00</published><updated>2011-01-06T19:29:56.040-08:00</updated><title type='text'>Adventures on Android NDK, Part I</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Over Christmas I brought home my shiny new Nexus S and downloaded the Gingerbread SDK. I'm pretty stoked about Gingerbread, since a lot of the changes between Froyo and Gingerbread seem really helpful for game developers. For instance, you can now write a game entirely in C++, without writing anything in Java.* And there's OpenSL ES, so finally some real support for sound.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;So, here's my story: former Xbox 360 developer, longtime DirectX user, Visual Studio pro, C++ devotee and C# aficianado... now trying my hand at Android development for the first time. I'll try and share what I've learned so far. This might be old hat to Android pros, but it's new to me, so maybe it'll come in handy for other developers with my kind of experience.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;I'm going to start this in Visual Studio. Android really wants you to use Eclipse. I'm totally going to do that someday, because I feel like I should know how to use something other than Visual Studio to write code. But not today. So I set up a makefile project and hooked it up to some code I copied out of the Android NDKr5 NativeActivity sample.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;b&gt;Cygwin Woes&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;First unpleasant realization: Cygwin is absolutely required if you want to build an NDK project on Windows. At least, if you want to build an NDK project that works the way it should. Most of the NDK make system's complications seem to stem from its support for backwards compatibility with different versions of the Android OS. Hmmm. I'm only interested in Gingerbread; do I want to break down the makefile and reconstitute it as an MSBuild project? Well... yes, yes I do. But not today. So, I installed Cygwin.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;Next bit of unpleasantness came when I hooked up the ndk-build script to my Visual Studio build action&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;. It took &lt;i&gt;forever&lt;/i&gt;&amp;nbsp;to start up. Well, maybe five or six seconds. It felt like forever. Yeah, I've worked on projects that took more than an hour to build, but this is just a couple hundred lines of C code--what gives. It turns out that newer versions of Cygwin start bash-completion on login, and that's slow. Not sure what it's doing (scanning my hard drive for things to complete?), but I'm pretty sure I don't need it. So &lt;a href="http://cfc.kizzx2.com/index.php/tag/cygwin-slow-performance-bash-completion/"&gt;out it goes&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;b&gt;Visual Studio&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;I added the NDK include directories to my project file under "additional includes." I told Visual Studio to ignore the standard includes because I don't want Windows stuff cropping up in my Intellisense. And yes, Intellisense works! Nice job, &lt;a href="http://www.wholetomato.com/"&gt;Visual Assist&lt;/a&gt;. :-)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;To build, I wrote a &lt;a href="http://code.google.com/p/ilewis/source/browse/Android/glTest/build.cmd"&gt;couple&lt;/a&gt; of &lt;a href="http://code.google.com/p/ilewis/source/browse/Android/glTest/build"&gt;scripts&lt;/a&gt;&amp;nbsp;to launch ndk-build and ant. The first is a DOS batch script to set up the paths and call Cygwin; the second runs everything inside of a Cygwin bash shell.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;The scripts are pretty simple, although there were a couple of tricky bits that I might post about later. Most of my trouble at was with the regular expression syntax in sed.** It's just slightly different than in perl, which is different from Visual Studio's system (which&amp;nbsp;is, inexplicably, different from the .Net regexp library... and so on). Ah, regexp, you never cease to surprise me. Anyway, after figuring out that in sed you escape the parens that surround a group, rather than *not* escaping them the way you do in perl, I was on my way.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;And... build works! The only thing that still sucks is that linker errors from the ndk toolchain don't contain the word "error," so Visual Studio doesn't list them in the error log. Well, that and the fact that I can't yet launch from Visual Studio. But that's a topic for another day.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"&gt;*&amp;nbsp;Although, now that there's a concurrent garbage collector, Java might not be that bad. But when it comes to managed languages, I'm a C# guy. So anything that gets me out of having to learn another language is good, at least for now.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;**&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;I usually use perl for this, for no really good reason other than I always have a Perl distro on my machine. Sed is actually a much better choice, because it operates on stdin as a stream, rather than buffering it up the way Perl does. For a task like munging compiler output, sed is totally the way to go.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-1098535996237175482?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/1098535996237175482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/adventures-on-android-ndk-part-i.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1098535996237175482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/1098535996237175482'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/adventures-on-android-ndk-part-i.html' title='Adventures on Android NDK, Part I'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4366277884301889887.post-8277516173062597789</id><published>2011-01-01T13:39:00.000-08:00</published><updated>2011-01-06T13:59:58.350-08:00</updated><title type='text'>I learned something today</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/_sqY98z7AHIM/TSY5TdHRfQI/AAAAAAAAAB0/iL58780Z_Qo/s1600/165px-KyleBroflovski.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/_sqY98z7AHIM/TSY5TdHRfQI/AAAAAAAAAB0/iL58780Z_Qo/s200/165px-KyleBroflovski.png" width="165" /&gt;&lt;/a&gt;Remember the old seasons of South Park, back when Kenny was still getting killed every episode? Back then, a lot of the episodes had sort of an "afterschool special" ending to them. Kyle or Stan would turn to the camera and say, "You know, I learned something today..." And then he'd explain whatever the moral of the episode was. Usually something sick and twisted, but that's what you expect from South Park, right?&lt;br /&gt;&lt;br /&gt;I feel like that line--"I learned something today"--pretty much sums up my whole career right now. My job (which I'll post more about later) involves a lot of learning, digesting, and regurgitating different technologies. I go down a lot of dead ends that don't turn into anything, but I still learn something from them. A lot of what I learn isn't groundbreaking, and sometimes it's not &amp;nbsp;even useful, but if I write it down then maybe it'll help keep others from making the same dumb mistakes I did.&lt;br /&gt;&lt;br /&gt;So, welcome to my blog. Hope you learn something. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4366277884301889887-8277516173062597789?l=ian-ni-lewis.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ian-ni-lewis.blogspot.com/feeds/8277516173062597789/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/i-learned-something-today.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/8277516173062597789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4366277884301889887/posts/default/8277516173062597789'/><link rel='alternate' type='text/html' href='http://ian-ni-lewis.blogspot.com/2011/01/i-learned-something-today.html' title='I learned something today'/><author><name>Ian</name><uri>http://www.blogger.com/profile/15703303217263175278</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sqY98z7AHIM/TSY5TdHRfQI/AAAAAAAAAB0/iL58780Z_Qo/s72-c/165px-KyleBroflovski.png' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
