Sunday, July 31, 2011

On Quitting Your Programming Job to Hack your Trajectory

TL; DR

Working in an industry I didn't like, quit job to work on independent projects for a few months to get a job I did like, got another job that I liked. Do what you want to do if you can as opportunities are not available forever and for everyone; however, set realistic goals. Life is short. Want something and go after it. Results may vary.

Table of Contents

  1. Inspiration
  2. Why to Quit
  3. Quit, Really?
  4. Preparation
  5. Happy Hacking
  6. The Hunt
  7. Ending

Inspiration

I went to my first Startup Weekend event and had plenty of fun. However, I didn't feel that I contributed enough to the team as a software developer because my team was doing something web-based, of which I had little experience. Therefore, I decided that whatever I had been doing on the side wasn't working. I needed to step it up a notch.

I ended up stumbling on a Hacker News thread about quitting not long after. The stories of others were comforting. I wasn't alone.

Why to Quit

I didn't like the industry norms, company culture, and advancement paths at my employer. When I joined, I was interested, but I couldn't imagine doing it for much longer. Times change. Hackers have certain luxuries in the software industry that I was denied (for example, working from home). I needed to leave before the incentive to stay was too large to abandon (employer match on 401k, domain experience, etc.).

You might be able to switch teams within your company to find a better opportunity. This option can be viable at big companies but only can provide limited change and might be not different enough for your liking.

You can work on what you really want to do on nights and weekends. This allows no decrease in compensation while slowly building skills to transition somewhere. However, this can be tough and may take forever depending on what you want to learn. Consider sacrifices that have to be made in one's social life, health, etc.

You could work part-time at your employer. This is a balance of compensation with time available for your future aspirations. However, this is not always an option.

One should consider all of these options and weigh the pros and cons. For me, I wasn't making enough progress on weekends and part-time was not allowed in my employment situation. Company culture was going to be the same regardless of what team I worked on. The recession contracted the opportunities at my former employer, reducing options. Quitting was the best option for me.

Quit, Really?

Depending on your risk tolerance and experience, the idea of quitting can seem reckless without another job in your hand. That is true to a degree as risk is undeniable. However, risk is relative. The software industry offers many opportunities; there are plenty of openings. I had savings, low debt, no dependents, and felt I had the potential to do better. Life is short; don't waste it.

Many people do not have the same opportunities as you. According to the UN, almost a billion people in the world are undernourished (download the publication for a definition of undernourished). And that's just food. Consider education, security, family, health, and more essentials that we take for granted. Human history is littered with pain and suffering. If you can't save those people, at least make the best of what you have and appreciate it.

Preparation

A small amount of work needs to be done upfront before one quits. The recommendations below are anecdotal based on my needs. Adjust accordingly.

  • Goals? What do you need to do after you quit to get the next job? Consider multiple projects to learn several skills and open up more opportunities. For example, I wanted to do web or mobile development. Therefore, I built an application for Android with Java and an application for the web using Ruby on Rails, learning client-side and server-side fundamentals. Also try goals not strictly about programming; for instance, I started a blog to share thoughts and also demonstrate communication skills. Consider the company and role you want.

  • Time? You'll need time for skills development, job applications, and moving if need be. I chose 3 months, but I can't imagine anything less: 7 weeks of hacking; a month for job hunting, hacking, studying, and apartment search; and remainder for moving. In hindsight, 3 months was a bit of a rush; consider 4 to 6.

  • Cost? For simplicity, you should have saved at least double the expected costs of unemployed time. This allows for new costs like private health insurance, a buffer for expenses until the first paycheck of the new job (received as late as 1 month after starting), and a general buffer for unknowns. Of course, this assumes low debt (for example, typical credit card debt). If you have large loans to pay off, quitting might not be viable.

  • Employer Notification. Company policies vary. The norm at my employer was 2 weeks notice, but I ended up giving a few months notice to figure out my options. Holidays can screw your planning.

  • Health Insurance. Definitely consider your health needs before quitting as you'll be footing the bill entirely for your insurance. Forget the employer-subsidized, generous health plan. Apply for a policy at least one month in advance. Approval can happen sooner (2 weeks for me), but the policy won't start until the beginning of the month anyway (align with job termination date if possible). COBRA coverage can be quite expensive so it usually isn't practical; however, the COBRA option could be retroactive, allowing one to deal with a lapse in coverage while waiting for approval. In my situtation, a high-deductible plan for around $100/mo. was reasonable. I chose a BCBS because I didn't want to spend a lot of time shopping and just aimed for a reasonable, reputable insurer. Even though it sounds like the right plan in this scenario, don't go with short-term health insurance: it only lasts for a certain amount of time, forcing you to reapply and potentially be rejected for a condition that occurred during your previous short-term policy.

  • Apartment Leases. For the apartment renters that might be moving to a new job, remember that lease cancellation notices might be required as early as 60 days ahead of move-out and relet fees are at least a single month's rent. Line it up so that you can quit, do your own thing for as many months as you need in your current place, and then just let the lease expire (with timely notification of course) when you move to the new job.

  • Confidence. You might be the only person to have done something like this. Your friends and family might be only reluctantly supportive or even scared, disappointed, or angry that you would take such risk. Ultimately, you have to make the right decision for your life. Do your best to maintain confidence (not easy) and keep your eye on the prize.

Happy Hacking

Stick to goals. Creation is quite satisfying.

One benefit of the free time is the opportunity to experiment. For example, how do you learn best? I prefer reading light overviews (lengthy but not too complicated) and then learning things incrementally as I need to develop features or fix bugs. For Android, I read two-thirds of the developer's guide and felt it was beneficial to get started even though it was a lot of reading. For web development, W3Schools was great for light overview with various blog posts, guides, and short book excerpts as supplements. I found that some resources provided very little value despite highly positive reviews (e.g., PeepCode screencasts).

Try to give back to the community via open source contributions, blog posts, or more. For example, I found a bug during my Android development in one of the stock applications. I submitted a patch, and it was merged into master branch within 2 weeks. I put the code for all of my projects on Github for public consumption as well as for potential employers to see. It is easy to belittle these small contributions but remember that something is better than nothing.

Take the projects to completion by publishing them; ideally, get some users. I was able to get 70 users within the first week on Android Market for my song alarm application without any promotion effort. For web applications, many hosting services offer free plans. Heroku was extremely easy to use for deploying Rails applications to the cloud. Share on Reddit, HN, Twitter, and elsewhere.

Consider going to tech meet-ups to meet others with similar interest and find potential job opportunities. I visited an HN meetup and met some interesting people doing start-ups and solo adventures like myself. For a platform-specific meetup, it's best to have started working on a project to at least demonstrate your interest.

The Hunt

Job-hunting can suck. Even though it's only like 3 paragraphs, writing a cover letter seems like a pain in the ass. It's especially encouraging when sending a job application and not receiving any response ever. This time is the low point, testing whether your decision to leave was worth it or a foolish mistake. Many postings are a reminder that you still don't have enough experience. Skip the big job sites like Monster and look at tech-centric places where interesting software companies are listed:

Even though GlassDoor is not tech-centric, it is certainly a place to visit for job openings because of the company salaries and reviews.

Ending

I ended up getting a job at a late-stage startup and am quite happier now. I got a decent compensation boost too in addition to the improved work environment and responsibilities. Quitting worked for me. Hopefully, this post is a call to action for another hacker out there on the sidelines with potential to do better.

Tuesday, April 19, 2011

How to Patch A Stock Android Application

Introduction

When developing an Android application that depended on the stock Android application Sound Recorder, I found a bug in the latter application. This post describes how one would patch such a stock Android application and submit the fix. The bug and the fix are not as relevant as the process of working with the Android Open Source Project (AOSP) code base. Gaps in the source documentation are filled in here.

Note that this post is tailored to development in Ubuntu 10.10 as that was my environment.

Prerequisites

Before fetching and building the AOSP, one should realize or do a few things:
  • Search the Android issue tracker and mailing lists to figure out if anyone has encountered this before and if a fix is in progress.
  • Browse the source to try to diagnose the issue before doing anything. Hooray for open source! Each application is in a separate git tree.
  • Once the issue is diagnosed and if it's not already an existing issue, post to the Android issue tracker. This allows others to see the status of the bug, make comments, and get others involved in a fix. If you can't fix it, at least someone else will be aware of the issue and could take on the effort.
  • It seems like the entire AOSP has to be built in order to build the single stock application that one wishes to patch. I could not find a source that described more surgical building without building everything else. Stock applications use private APIs that are not published in the SDK so those dependencies have to be built. It's probably just easiest to build everything to get to the task at hand.

Initializing the Build Environment

The official steps at the time of the writing work with the following exceptions:
  • OpenJDK 6 works. You do not have to get the Sun JDK. To check your installation, use the command "java -version" in a terminal.
  • The required packages list is wrong; apt-get will complain that it cannot locate packages. See the first answer on this Stack Exchange post.

Downloading the Source

Nothing wrong actually happened here using the official steps! Download time varies depending on your interwebs connection; it took several minutes for me. My working directory was $HOME/aosp; all following instructions will assume this is your current directory.

Building and Running

The official steps did not indicate how much pain would be involved. A bunch of issues were encountered.

Processor Architecture 32-bit vs. 64-bit

Based on mailing list discussions, building is only supported for 64-bit machines for releases after Froyo (v2.2), but the community has found ways to patch the source to allow 32-bit builds. When trying to build on a 32-bit machine, you'll get a warning from the make command. A few makefiles need to be editing for building to proceed. Do as follows:
  • In build/core/main.mk, comment out the check for 64-bit versions (search for 64 to find the if-statement).
  • Search for makefiles with explicit 64-bit build flags and comment out variable assignments that add those flags:
    find . -name '*.mk' | xargs grep m64
For example, here is the changes I made to one of the makefiles with explicit flags:
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index d3ab3dd..be99ad4 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -249,9 +249,9 @@ LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211
 endif
 
 ifdef CONFIG_DRIVER_PS3
-L_CFLAGS += -DCONFIG_DRIVER_PS3 -m64
+L_CFLAGS += -DCONFIG_DRIVER_PS3 # -m64
 OBJS_d += src/drivers/driver_ps3.c
-LDFLAGS += -m64
+#LDFLAGS += -m64
 endif
 
 ifdef CONFIG_DRIVER_IPHONE

Once the build starts, it took at least an hour on my machine (Core 2 Duo, 2.0 Ghz). It's building almost everything you can think of except the kernel. The built binaries will be in the out directory.

Emulator Fails to Run

Before applying our fix, let's at least make sure that our environment works. Run the emulator at out/host/linux-<ARCH>/bin/emulator.
emulator: ERROR: You did not specify a virtual device name, and the system directory could not be found.

If you are an Android SDK user, please use '@' or '-avd ' to start a given virtual device (see -help-avd for details).

Otherwise, follow the instructions in -help-disk-images to start the emulator

By default, the emulator looks for default system images (*.img), containing the root file system among other things, in $ANDROID_PRODUCT_OUT. This shell variable is defined only if you ran the lunch program in the same shell as the emulator. You can rerun lunch in any shell to define these variables.

Do not use a prebuilt SDK to test applications built from the master branch of AOSP. They are built with a special SDK version that is newer than any prebuilt SDK version; therefore, the patched application will fail to install (INSTALL_FAILED_OLDER_SDK). Using the Android Asset Packaging Tool (aapt), we can see this special version of the applications built:

$ aapt dump badging $ANDROID_PRODUCT_OUT/system/app/SoundRecorder.apk 
package: name='com.android.soundrecorder' versionCode='10' versionName='AOSP'
sdkVersion:'AOSP'
targetSdkVersion:'AOSP'

No SD Card

If testing requires a SD card, create one that the emulator can use as follows:
out/host/linux-<ARCH>/bin/mksdcard SIZE $ANDROID_PRODUCT_OUT/sdcard.img
See the help documentation for how to express size (mksdcard -help). For example, my SIZE was 32M to produce a 32 MiB file. The second argument is the default location of the emulator's SD card image file.

Using a Test Application

I used my Android application to exercise to demonstrate the bug in the stock application. To install your application, use the Android Debug Bridge (adb):
$ out/host/linux-<ARCH>/bin/adb install LOCATION/OF/TEST/APP

Applying Your Fix

Assuming that the emulator is operational and you've demonstrated the bug, apply the fix and rebuild. The shell function mm is defined in build/env.sh and will rebuild only the module in the current directory.
$ cd packages/apps/THE_APP_TO_FIX
$ (edit files as necessary)
$ mm 

Restart the emulator to pick up the changes. Even though the Android Debug Bridge (adb) provides a sync capability to push the changed file to the emulator, you might get an "out of memory" error. Let's keep it simple for now.


Submitting the Fix

After the fix has been verified and committed locally, it's time to submit it to the world! Before you can use the repo tool to upload the fix, set up your account on r.android.com:

  • Submit your SSH public key as uploading uses the SSH protocol.
  • Sign a contributor agreement. Individuals can do this completely online.

The successful upload will be viewable at the source review site. To improve the chance of getting accepted, add a reviewer who was involved in the development of the application. The commit log should indicate who would be most appropriate as a reviewer.

Closing

For such a simple patch, I ended up doing a lot of work, but it was worth it in the end. I've been a user of open source for a while but have never contributed back until recently. Even though it is a small contribution, it's a start. A lot of people making small contributions add to something big. Also, it's awesome to think that my small change could be distributed to millions of devices.

Saturday, April 2, 2011

Simple, Effective Password Management with Keepass and Dropbox

Disclaimer:  Even though I used KeePass for 2 years and donated to the project, I have migrated to LastPass as I wanted a product with support for the long-term. It's also more convenient with browser integration (auto-filling of forms instead of copy-pasting), it doesn't have a .NET dependency, and I don't have to rely on a separate party like DropBox for backups.

Have you ever counted how many online accounts you have?  Online accounts are used for almost everything in our lives:
  • Social networking
  • E-mail
  • Finance & credit
  • Utilities
  • Shopping
  • Insurance
And more.  How do you manage all of the passwords?  With so many accounts, it's easy to be lazy by writing passwords in plain text file, reusing passwords across sites, using very weak passwords, or even depending exclusively on security questions to get into an account because it's used rarely (e.g., biannual payments to a service).  After examining my accounts, I even found that the password to one account was a username of another.  I also found out that I had over 20 online accounts.

Perhaps you think it's not a big deal.  Perhaps.  But have you ever read about how a bunch of internal documents from Twitter were released 2 years ago?  It's intriguing.  The hacker didn't use complex technical exploits at all; he simply broke into one weak account and used it to work up the chain of more valuable accounts.

Luckily, there are mature tools out there to help manage password-authenticated accounts.  I use KeePass, an easy-to-use password manager that achieves the following:
  • Confidentiality: all stored passwords and account information are stored in an encrypted file.
  • Strength: the program can generate long and complex passwords for you (less vulnerable to someone guessing or cracking the password).
KeePass is also multi-platform as it can run on Windows as well as Linux (I've actually tested this).  In short, you remember one master password that is used to derive a key to encrypt a password database file.  Provide the master password to access and modify the password database.  When you need to use a password, use the program to copy the password from the database and then paste it into the web browser.  When coming up with a master password, consider using a long but simple password like a sentence or a quote.  You must be able to remember it but prevent others from simply guessing it.  My master password is over 30 characters long.

When converting passwords from old to new KeePass-generated ones, consider the following:
  • After changing your password, test it!  You might have accidentally pasted the wrong password, or the site did not accept the password.  Some sites will not accept the generated password generated using KeePass default settings.  For example, some sites have maximum password lengths like 8 characters (WTF?), but KeePass generates 20-character passwords by default.  Even worse, you might not realize this until you change the password, log out, and then fail to log in.  If you copy a password into a field with a maximum length restriction, the password will be truncated to the maximum length without notice.  Do a quick check on the password rules for the site when changing the account password.  Then modify the password generation rules to shorten the password as appropriate for that specific password (stick with defaults otherwise). 
  • One site actually prevented pasting of the password using Javascript.  While it might be instinctive to disable Javascript in the browser and paste anyway, this can cause more trouble.  I just displayed the password in KeePass and manually typed each character.  Lame.
  • For some reason that I didn't look into deeply, I couldn't paste my password into a terminal prompt in GNOME on Ubuntu when creating a SSH key pair with passphrase.  I had to use the key creation tools in Ubuntu 10.10:  System >> Passwords and Encryption Keys >> My Personal Keys.    
Great, say you've changed your passwords on many of the accounts to stronger KeePass-generated passwords.  But now there is a new problem:  backup the password file or risk losing the passwords to every online account.  I use Dropbox to backup my password file.  The free plan has plenty of space and can be accessed and updated from multiple machines cross-platform.  

Now what if you want to secure the Dropbox account with a strong KeePass-generated password?  Make the password database a public file in Dropbox.  Then you can access it from anywhere without barriers and still retain password confidentiality.  I also keep a copy of the KeePass binary zip as a public file so that I can easily set up any machine to access my passwords.  Grab the password file, the binary zip, and go!  The only catch is that you have to remember the master password (obviously) and the URLs to the public Dropbox files.  The URL is in the following format:

http://dl.dropbox.com/u/USER_ID_NUMBER/YOUR_FILE_NAME.  

One can figure out a good way to remember the URLs:  note it down in your phone, use a copy of the password database to get to the latest password database, etc.

But what about mobile?  KeePassDroid works too for Android smartphones.  You can put a copy of the password database on the smartphone (for simplicity if rarely authenticating as I do) or use Dropbox on your Android smartphone to always use the latest password database (haven't tested this).     

Using this setup for several months now, it has been quite easy and definitely more secure than my previous password mismanagement.  Comments on improving the setup are welcome!