Neil Loknath

mostly programming

Ticklebug: An Android-based PC Remote

I created Ticklebug to solve a problem for myself, and I’ve decided to share it.

Ticklebug was born as result of saying goodbye to cable subscription fees in our home. Bye, bye fees. Bye, bye cablebox. And, Hello, HTPC!

The Need

Obviously, I wasn’t going to be walking up to the television set to fiddle around with a keyboard and mouse everytime I wanted to watch something. That would be way too much exercise for something that’s really supposed to involve as little exercise as possible. Initially, my solution for this problem was one of those wireless keyboards with an integrated trackball. Don’t get me wrong, the combination is pretty awesome. After awhile, though, I noticed that I was playing with my phone a lot of the time while watching TV. So, I thought it’d be great if I could use my phone as a remote control!

I began searching for and trying various Android apps for remote controlling my HTPC. However, I wasn’t completely happy with any of them. In my ideal remote control app, I wanted the following features:

  1. A maximum surface, blank canvas that acts like a touchpad, very similar to how laptop touchpads behave.
  2. Mac and Windows support, as I use both regularly.
  3. Voice commands so I can tell my computer what I want it to do.
  4. Zoom! Because, as great as high-def is, sometimes things are just hard to read.

Features

Ticklebug has a long list of features, so I won’t go over everything. What I will do, though, is I’ll go over the above list and tell you a little about how Ticklebug handles each.

Touchpad

Ticklebug maximizes your mobile device’s screen space keeping it uncluttered at all times. There are a very limited number of buttons. To interact, touches, drags, and taps are used liberally. To make Ticklebug super easy to use, the gestures are very familiar:

  • Drag a finger to move the mouse pointer
  • Drag two fingers to scroll within windows
  • Long-press a finger and drag to move or resize windows
  • Single-tap to left click and double-finger-tap to right click
  • Swipe left or right to navigate back or forward, respectively, when web browsing

Cross-platform

I use a Macbook most of the time. But, my HTPC runs Windows 8. I’m a faithful subscriber to Netflix, and running Windows just makes using the service much easier than using another operating system. Thus, I needed Ticklebug to be cross-platform to get the most out of it. As a result, there are desktop applications for both Mac and Windows.

Voice Commands

What’s cooler than speaking instructions to your computer? Nothing! So, I gave Ticklebug the smarts to understand a few commands:

  • Say Google followed by some search words and your default browser will load with the search terms ready to go in Google’s search bar.
  • Say Open followed by some site name and your default browser will load it. For example, say open youtube dot com, and http://youtube.com wlll load.

And, in the paid version of Ticklebug:

  • Say Start followed by the name of some executable file, and your computer will run it. For example, say start notepad, and Notepad will start.

What’s great about the last command is that you can create your own voice commands to do just about anything! For example, on Windows 8, Netflix has some weird, wild, hidden file name making it difficult to launch using a voice command. However, the application will run if you type netflix:// into a browser. We can use this piece of information to create a custom voice command.

On my computer, I’ve created a script named netflix.bat and saved it in a directory that’s specified in my PATH environment variable. The contents look like the following:

1
2
3
:: Launch Netflix app on Windows 8
cmd /c "start netflix://"
exit 0

Now, I can say start Netflix to launch the app without typing a thing!

Pinch-to-zoom

Again, using Netflix as the example, those little video thunbnails in the Windows 8 app are pretty hard to read most of the time. I really wanted to be able to zoom in the way you can when using your phone’s web browser. So, in Ticklebug, you can move two fingers apart to zoom in and move two fingers together to zoom out. And, this gesture can be used within any application, including the desktop.

In Stores Now!

Ticklebug remote for Android

If you have an Android device running Android 4.0 or higher, give Ticklebug a try!

No Comment

I was always taught in school to liberally apply comments to my code. For a long time, I considering this practice a good one. I no longer do, however.

Before you write me off as a lame-o programmer, to illustrate why I feel this way, let’s walkthrough some examples using an old favourite algorithm: merge sort. For the sake of this exercise, though, let’s assume that merge sort is not a widely known algorithm, so we don’t fall into the it’s merge sort, duh! trap.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def mergesort(a):
  if len(a) <= 1:
      return a
  m = len(a) / 2
  l = a[:m]
  r = a[m:]
  return merge(mergesort(l), mergesort(r))

def merge(l, r):
  li = 0
  ri = 0
  m = []
  while li < len(l) and ri < len(r):
      if l[li] < r[ri]:
          m.append(l[li])
          li += 1
      else:
          m.append(r[ri])
          ri += 1
  if li < len(l):
      m.extend(l[li:])
  else:
      m.extend(r[ri:])
  return m

Here we have a completely correct sorting algorithm coded in one of my favourite languages, Python. In my opinion, though, correct code is not quite good enough. This code could be improved in some ways. Let’s assume that liberally adding comments is one of these ways.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def mergesort(a):
  """Returns a sorted list.
 """
  # Base case for recursive algorithm is when
  # there is 1 or less elements. In either case, we call 
  # the list sorted.
  if len(a) <= 1:
      return a
  # Find the middle of the list
  m = len(a) / 2
  # Split the list into halves
  l = a[:m]
  r = a[m:]
  # Merge the two sorted halves 
  return merge(mergesort(l), mergesort(r))

def merge(l, r):
  """Returns a merged sorted list.
 """
  # Track the positions of the lists starting at index 0
  li = 0
  ri = 0
  # Initialize an empty list to store the final sorted list
  m = []
  # Loop while both halves still have unprocessed elements
  while li < len(l) and ri < len(r):
      # When the left list element is less than the right
      # list element, we add it to the final sorted list
      # and increment the position for the left side. Otherwise
      # we do it for the right side
      if l[li] < r[ri]:
          m.append(l[li])
          li += 1
      else:
          m.append(r[ri])
          ri += 1
  # Since one list has been completely processed, we extend
  # the final sorted list with the sorted elements remaining in
  # the other list
  if li < len(l):
      m.extend(l[li:])
  else:
      m.extend(r[ri:])
  return m

My once Intro to Algorithms professor would really like this version. But, you, however, shouldn’t like this. Let me explain.

Since I’m assuming that merge sort is an unknown algorithm, in an effort to improve readability, I’ve added lots of prologue comments. They basically reiterate what the code is doing. To me, these types of comments add too much clutter and may over-complicate something that wasn’t all that complicated to begin with (like in this case). For a college professor receiving something like this from a student as an assignment, these comments could be useful, as they could give insight into whether or not a student understands what the code is doing. However, in a work setting, it should be a fair assumption that your colleagues can read the code to figure out what the code is doing.

It could be argued, though, that without the prologue comments, the readability is suffering because the variable names don’t convey enough about the code. That’s a valid point. So, let’s try something different.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def mergesort(unsorted):
  """Returns a sorted list. 

 The passed list is recursively halved 
 into sublists until each sublist has one or less elements. Then, 
 the sublists are merged together such that their elements are in order.

 Worst case time complexity is O(n log n).
 Worst case space complexity is O(n).
 """
  if len(unsorted) <= 1:
      return unsorted
  
  middle = len(unsorted) / 2
  left_half = unsorted[:middle]
  right_half = unsorted[middle:]
  
  return merge(mergesort(left_half), mergesort(right_half))

def merge(left, right):
  """Returns a sorted list as a result of merging 
 two sorted lists.
 """
  left_index = right_index = 0
  merged = []
  
  while left_index < len(left) and right_index < len(right):
      if left[left_index] < right[right_index]:
          merged.append(left[left_index])
          left_index += 1
      else:
          merged.append(right[right_index])
          right_index += 1
  
  left_remaining = left_index < len(left)
  if left_remaining:
      merged.extend(left[left_index:])
  else:
      merged.extend(right[right_index:])
  
  return merged

This version follows the no comment is the best comment approach. The variable names have been modified (and according to Python style guidelines) to convey their purpose making the code self-documenting and rendering all the prologue comments unnecessary. The code itself effectively describes what the code is doing.

The function headers have been improved such that callers can discover what the functions do without reading a single line of code. This is especially important for public interfaces and let’s us use tools like pydoc to easily share code documentation.

You may be wondering, what’s the big deal? Let’s just refactor and keep the comments too so we can have the best of both worlds! The problem is that adding unnecessary comments creates another set of things to maintain. It’s even worse when the code changes and the comments are orphaned. Suppose a colleague comes along and changes the code again based on comments that incorrectly describe code that no longer exists. Now, things are really a mess. Then, your colleague goes on vacation and a bug surfaces related to all these changes and you’re stuck git bisect‘ing your way through it all to figure out where things went wrong! So, I’ll state this again very explicity: liberal code commenting is wasted effort; make your code more self-documenting because no comment is the best comment.

Octopress, FTW!

Bye bye, Wordpress. Hello, Octopress!

I used this handy tool called exitwp to export all my Wordpress posts into Markdown format for the Jekyll-based Octopress to consume.

I like writing in Markdown. Concise, quick, and painless. So, now I’m blogging using two of my favourite tools: git and vim! And, the blog no longer needs PHP or MySQL, so switching to static hosting will save me a few pennies.

↓ Happy Dance! ↓

Happy Dance!

Moxy

She’s alive. And, her name is Moxy.

Simply put, Moxy is an HTTP proxy that acts like a regular HTTP proxy, but it also allows you to mock responses, including support for delays and conditional statements.

Why is this useful? Consider the following use case…

You’re working on a team of two. You’re responsible for the client code and the other handles the server side. Let’s call the other, Backend Billy. Backend Billy is great most of time. However, lately, he’s been a little distracted, affecting his ability to deliver on the RESTful API that you need to get on with your client side work. Of course, being a good team, you spec out the API beforehand and have an interface to work against. You’ve got a bunch of code written up, but you can’t test real, live network requests because the API service doesn’t exist yet. Moxy can help here.

Let’s say you’ve spec’d out three endpoints…

http://api.awesomeapp.com/v1/awesome http://api.awesomeapp.com/v1/awesome/add http://api.awesomeapp.com/v1/awesome/:id

Using Moxy, you can add the following configuration entries into moxy.conf

url http://api.awesomeapp.com/v1/awesome/?$
  get 200 awesome.json

url http://api.awesomeapp.com/v1/awesome/add
  get 400 awesome_add_error.json
  post 200 awesome_add.json

url http://api.awesomeapp.com/v1/awesome/?\?id\=.+
  get 400 awesome_id_error.json
  if created: get 200 awesome_id.json

Now, with Moxy up and running and your system configured to use her as an HTTP proxy, you can happily test your client code as if the backend is fully implemented, even though Backend Billy is still dilly dallying.

Notice the line that reads if created: get 200 awesome_thing.html. It’s a conditional statement with a condition called created. This allows the success response to be delayed until necessary. You can see and manipulate all conditions by browsing http://localhost:9889/config/conditions.

Additionally, let’s say you’ve added some nifty error handling logic when the add request takes longer than 10 seconds. To test, you can modify moxy.conf as follows…

url http://api.awesomeapp.com/v1/awesome/add
  if delay: delay 13000
  get 400 awesome_add_error.json
  post 200 awesome_add.json

This tells Moxy to delay the response for 13 seconds if the delay condition evaluates to true.

And, if none of that interests you and you just want Billy to get back to work, you could sneak on to his computer and configure Moxy with something like…

url ^.+\.facebook\.com
  get 301
  header Location http://awesomeapp.com/api/documentation

Moxy is written in Python, open source, and available on Github.

SyncMyPix 0.2

Remember SyncMyPix?!?

I do…vaguely. I’ve been putting off integrating some fine work from contributors, and I figured that it’s been long enough!.

I’ve finally gotten around to merging in their work creating version 0.2. Here’s a quick summary of what’s gone into this release:

  • Update contributors in README
  • Remove read log permission
  • Default to high quality photo setting and remove setting
  • Fix problem with photos not getting cached to SD card
  • Improve Greek name matching (thanks Diomidis Spinellis)
  • Fix name matching when names contain Turkish characters (thanks Deadknight)
  • ICS fixes (crop view, etc.)
  • Use Facebook Connect SDK instead of homegrown API library
  • Attempt to get highest resolution photos possible from Facebook

Those last 3 are also thanks to Deadknight.

Unfortunately, I haven’t had any time to work on SyncMyPix, hence the delay with getting out a release with all these improvements. I’ve been quite busy with work and other projects. So busy, in fact, that I’m calling this my last release of SyncMyPix. I haven’t tested this enough to feel comfortable releasing it through the market (I actually did publish it, but later removed it). But, I didn’t want that to stop me from sharing this, so the downloads are available from Github. I’m going to be removing SyncMyPix from the store a week from today.

I’m glad it’s been useful to a lot of people, but I’ve got to move on to other things. I’ll continue to host the source code on Github, as I’d love to see someone take the app and improve on it, as it seems there are still people that are interested. So, please, feel free to fork it and make it your own!

Permission Denied

Yes, that is the one and only Gandalf. The powerful wizard from Lord of the Rings. In this case, however, I’m using Gandalf as a representation of the Apple App store review process. Just like Gandalf, the review process tells app developers “you shall not pass!” when an app isn’t worthy of distribution. For developers, it can be an annoyance. For users, it can be a good thing. The review process acts as a seive, separating wanted and unwanted elements. For Apple, depending on the weather, unwanted can mean a variety of things. But, the good thing is that unwanted always includes things that are malicious. Google Play, the Android App store, unfortunately, doesn’t have this sieve.

What the Play store has is a permission system. When you install an app, your phone will present with an are you sure? type of screen listing a bunch of things which may or may not make any sense to you, depending on your level of tech savviness. The permission system basically makes you the gatekeeper. If you don’t think a given app should be allowed to have permission X, you can choose to not install or update it.

If you’re like me, you occasionally get caught up in the excitement of a new app and…

num, num, num your way through screens without even realizing that you were presented with a warning.

Now that I’ve caught myself doing this, I’m trying to pay more attention to what I’m installing. Right now, for example, an app I use a lot has an update in the store. Since it’s requesting a few new permissions, it requires user intervention before getting installed. The permissions of key interest are Send SMS and Receive SMS. I don’t like this. I don’t like the idea of an app that previously had no interest in my SMS messages suddenly becoming interested in them. Kinda creepy, right?

So, here’s what I did to vet this app update:

  1. Plugged my phone into my computer
  2. Issued adb pull /data/app/X.Y.apk to copy the app to my computer
  3. Updated the app from Play store
  4. Tried it and decided I didn’t think it deserved its requested permission
  5. Issued adb push X.Y.apk /sdcard
  6. Re-installed the old version from the SD card

Not very Gandalf, so I think Google needs to do better.

To sum up the above, I’m not happy with the new update for app X.Y. But, I’m fine with the previous version. With this in mind, here are some ideas of things that could help with this problem:

  • Let users, at minimum, go back to their previously installed version. Developers could be given analytics on this so they know when their updates are unappreciated. This could also help in the case where an update is buggy.
  • Let users block an app from using permissions but continue using the app. In this case, it would be up to the developer to fail gracefully in the event of a blocked permission. A way to cross permissions off my list of granted ones in the Play store might be nice.

To me, these ideas, if implemented, would be very unobtrusive for the user. This means that we would have the opportunity to be better gatekeepers and enjoy more apps.

Sometimes, though, I wonder, am I just a minority? Are others just as cautious as me? Well, if you’re not, I think you should be. I don’t use third-party keyboard apps because I don’t like the idea that they can log my keystrokes. And, if I give them Internet permission, the data can be transmitted anywhere. Again, creepy.

Security is tough. More options might make things a bit more complicated. Nonetheless, I think having more control over my security and privacy is a good thing, especially in the case of the gatekeeperless Google Play store.

Rdio Playlist as CSV

So, you use Rdio. You’ve created some kick-ass playlists. But, now you need to export them. Maybe you like having backups? Or, maybe you need to give a song list to a DJ? (like I needed to) Whatever the reason, you need to export them. But, Rdio has no export feature. What to do?

Enter this bookmarklet I whipped up. Slap the below code in a bookmark, save it, click while viewing an Rdio playlist, and you’ll have yourself a new tab containing a comma delimited file in Track Name, Artist, Album order.

This will work until Rdio changes their HTML. But, hopefully, they’ll provide the functionality themselves first.

Consoleme

Let’s face it. Geeks like logs. Scrolling text, line by line, running programs spewing out meaningful information by the second. Comforting, isn’t it? Don’t you just wanna tail -f /var/log/syslog right now!?!

Output. Need More Output!

If you’re like me, when using your magical iOS devices, you don’t always feel quite at home. There’s something missing: the system log! You can’t view it! Well, not all that easily, anyway.

Solution? consoleme!

We all like easy, even developers like me. Enter, consoleme! An app I wrote to allow you to view your iOS device’s system log right on your device without hooking it up to your Mac.

Some things it does:

  • Persistent log history
  • E-mail to your buddies
  • On-demand, instant refresh

It’s also pretty easy to use. A recent snapshot of the log is loaded when the app starts. Once the app has started, simply tap anywhere on the screen to perform additional actions. And, that is all there is to it!

Screenshots

I know you like pictures. So, here are some pictures…

You Want It? You Got It!

It’s not groundbreaking stuff, I know. There are other apps. But, this one is free and it’s available, source code and all, on github. It depends on my other project, NLOSyslog, which has been included in the consoleme project. Both projects are in their infancy. Thus, there are no official releases. However, everyone is more than welcome to the source or, even better, send me pull requests!

Cache Grab

I came across this today. Whip down to question 11 where is reads…

I want to use SWAP or COMPCACHE to increase the available RAM on my Android phone. Is that safe ?

The answer there states compcache is safe while swap is considered unsafe. A closer looks tells a slightly different story, however.

Compcache is a system that conserves memory by compressing a portion of it. This portion is readable by the root) user at /dev/block/ramzswapN, where N is some number. This means that any application running on a device utilizing compcache could have portions of its address space readable from the above mentioned path.

I have a rooted device running custom firmware with compcache installed. So, I tried reading data from the cache after using some apps that contained sensitive information. As I expected, I found that there were pieces of that information in the cache. As with the case I explored previously, passwords and encryption don’t help here.

So, would I call compcache any safer than swap? Nope.

The Root of It

You’ve heard of Android. But, what do you know about Rooting? What the heck is that you might ask? Custom community developed ROMs are all the craze these days and in order to install them, you’ll need to perform a process called Rooting). This gives you complete, no holds barred access to your device. Sounds great, right? But, consider what would happen if your precious device were to fall into the wrong hands? Here is an example of what could go wrong.

Using the Android SDK, with your device wired in via USB, you can remote shell into it via adb shell. From here, you can poke around and find all sorts of things. Issuing ps within the shell will display output similar to the following:

USER     PID   PPID  VSIZE  RSS     WCHAN    PC         NAME
system    497   122   114564 18008 ffffffff afd0ee3c S com.android.settings
app_16    522   122   117952 13276 ffffffff afd0ee3c S com.google.android.voicesearch
root      539   2     0      0     c006a118 00000000 S tiwlan_wifi_wq
wifi      543   1     3112   752   ffffffff afd0deb4 S /system/bin/wpa_supplicant
app_10    711   122   109676 14248 ffffffff afd0ee3c S com.android.providers.calendar
app_57    764   122   0      0     ffffffff 00000000 Z droid.apps.docs
app_17    816   122   119136 23252 ffffffff afd0ee3c S com.android.vending
dhcp      875   1     936    372   c00d6198 afd0ec0c S /system/bin/dhcpcd
app_14    932   122   105392 12868 ffffffff afd0ee3c S com.android.defcontainer
app_30    962   122   105400 12272 ffffffff afd0ee3c S com.svox.pico
app_43    976   122   135648 22348 ffffffff afd0ee3c S com.google.android.apps.maps
app_42    996   122   105376 12216 ffffffff afd0ee3c S com.android.vending.updater

This is a listing of all running processes on the device. Each process has a unique identifier called a PID. With root access, we can actually dump process memory (live application data) to a file by sending the process the SIGUSR1 kill signal). The generated file is called a heap dump and can be created by issuing kill -10 _pid_ in the shell.

You’ll know it was successful because you’ll see something similar to the below in the log:

I/dalvikvm( 1003): threadid=3: reacting to signal 10
I/dalvikvm( 1003): SIGUSR1 forcing GC and HPROF dump
I/dalvikvm( 1003): hprof: dumping VM heap to "/data/misc/heap-dump-tm1326509736-pid1003.hprof-hptemp".
I/dalvikvm( 1003): hprof: dumping heap strings to "/data/misc/heap-dump-tm1326509736-pid1003.hprof".
I/dalvikvm( 1003): hprof: heap dump completed, temp file removed
D/dalvikvm( 1003): GC_HPROF_DUMP_HEAP freed 1461 objects / 141080 bytes in 5951ms

Now that the process memory has been saved to the file system, it can be pulled off the device and processed by a memory analysis tool such as MAT

I’ve tried this with one of my devices, gathering heap dumps for a few different processes. Not too surprisingly, plenty of data I’d rather not have just anyone taking a peek at was readily available. In some cases, passwords were pointed out quite clearly.

For a legitimate software developer, this functionality can be great for debugging / troubleshooting purposes. However, for the everyday user, this is quite the opposite. A thief could swipe a given device and, if rooted, have access to a lot of live, possibly private, data. Unfortunately, password protecting your device does not prevent this. And, apps that secure data with passwords or encryption may be at risk too since the secured data could already be readable in memory.

Thankfully, Google has closed this vulnerability as of Android 2.3 by disabling heap dumps via the previously mentioned kill signal. This doesn’t mean that devices running this software are impenetrable. But, it does make this type of hack a bit harder.

So, the moral of the story is that a malicious individual will likely find a way to get the information they want, if they’re talented (some may prefer the term evil?) enough. However, if you value your privacy, you should be aware that you may be giving it away by rooting your Android devices.