)]}'
{
  "commit": "428975efd7c4f22f430410b32b3026ecd961d1bd",
  "tree": "e651bc92d9687ff2ad1c403689763af8bb9026a5",
  "parents": [
    "45e9efb9f75f85be6b8b03c130bc5c9e1080f7a6"
  ],
  "author": {
    "name": "John Grossman",
    "email": "johngro@google.com",
    "time": "Sun Feb 12 17:51:21 2012 -0800"
  },
  "committer": {
    "name": "John Grossman",
    "email": "johngro@google.com",
    "time": "Sun Feb 12 17:51:21 2012 -0800"
  },
  "message": "Put a bandaid on a segfault in timed audio track handling.\n\nAdd a bandaid to prevent a segfault which can occur while handling\ntimed audio buffers.  There is a deeper problem which should\neventually be addressed, but for now this fix should prevent any\ncrashing.\n\nThe deeper problem is as follows.\n\nWhen the AudioFlinger mixer gets data to mix from an AudioTrack, it\nends up getting a structure filled out which points into an IMemory\nregion owned by the AudioTrack.  Unfortunately, this structure is not\nholding a refcount on the IMemory which it points into.  If the\nIMemory refcount hits 0 and the chunk of RAM is retuned to the binder\nheap it came from, there can still be a Buffer object being held by\nthe AudioFlinger mixer which points into the region of memory which\nwas retuned to the binfer heap.  If AF reads from this buffer, it\ncould read corrupt data (if the region of memory gets handed back out\nto a writer), or it could segfault (if the heap has been freed and the\npages unmapped).  Similar problems could happen if AF attempts to\nwrite to the buffer, heap corruption in one case, segfaulting in the\nother.\n\nIn the past, this has not been an issue for AF, because tracks\nallocate a single IMemory (which serves as a ring buffer) and the\nIMemory lives for as long as the track lives.  As an artifact of the\nway the code came out, the mixer cannot be holding a Buffer structure\npointing into the IMemory which used to be owned by a track if the\ntrack no longer exists.  Tracks cannot come into or out of existence\nduring a mix operation, which is the only thing which makes this safe.\n\nTimedTracks work differently, however.  Timed tracks each allocate a\nsmall binder heap, and then hand out IMemory instances  broken out of\nthis heap.  The heap lives as long as the track, so the worst which\ncould happen here is that a TimedTrack\u0027s IMemory gets returned to the\nheap while there is still a buffer structure in flight pointing into\nthe memory region, then the region gets handed out again and\noverwritten by new data causing the mixer to mix the wrong audio.  The\ntiming to cause this to happen is very difficult to encounter, and you\nto generate the timing conditions required, you need to be in a pretty\nbad failure state where audio is already breaking up and skipping, so\nits unlikely that anyone would notice (which is why I\u0027m band-aiding\nthe segfault and letting the deeper issue slide for now).\n\nIn general, however, it might be a good idea to revisit this buffering\ndesign.  On principal, if someone is going to hold pointers into a\nrefcounted object, they should be holding a ref on the object at the\nsame time.  Failure to do this will usually lead to a situation where\nthere are corruption or segfault issues, or to a system where the\nrefcounted object\u0027s lifetime must be implicitly managed very carefully\nin ways which are usually non-obvious and are easy to break by new\nengineers on a project.\n\nChange-Id: Ib391075395ed0ef46a03c37aa38a82d09e88abeb\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "dbad3d9bda54f74058f411e63ae419c3dd73d525",
      "old_mode": 33188,
      "old_path": "services/audioflinger/AudioFlinger.cpp",
      "new_id": "6efd6718ac72a6d9560b47c6727e757cbf1a3c84",
      "new_mode": 33188,
      "new_path": "services/audioflinger/AudioFlinger.cpp"
    }
  ]
}
