Allow to specify output dir for heap_profile.

Test: manual

Change-Id: I2f5899a7b8137906ef4a15e2d92796636cd21ac3
diff --git a/tools/heap_profile b/tools/heap_profile
index cef8e2b..f16251d 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -234,6 +234,12 @@
       "--print-config",
       action="store_true",
       help="Print config instead of running. For debugging.")
+  parser.add_argument(
+      "-o",
+      "--output",
+      help="Output directory.",
+      metavar="DIRECTORY",
+      default=None)
 
   args = parser.parse_args()
 
@@ -345,6 +351,22 @@
         '> /dev/null'
     ])
 
+  profile_target = PROFILE_LOCAL_PATH
+  if args.output is not None:
+    profile_target = args.output
+  else:
+    os.mkdir(profile_target)
+
+  if not os.path.isdir(profile_target):
+    print("Output directory {} not found".format(profile_target),
+            file=sys.stderr)
+    return 1
+
+  if os.listdir(profile_target):
+    print("Output directory {} not empty".format(profile_target),
+            file=sys.stderr)
+    return 1
+
   perfetto_pid = subprocess.check_output(
       ['adb', 'exec-out',
        PERFETTO_CMD.format(cfg=cfg)]).strip()
@@ -386,13 +408,15 @@
     time.sleep(1)
 
   subprocess.check_call([
-      'adb', 'pull', PROFILE_DEVICE_PATH, PROFILE_LOCAL_PATH
+      'adb', 'pull', PROFILE_DEVICE_PATH,
+      os.path.join(profile_target, 'raw-trace')
   ], stdout=NULL)
   subprocess.check_call(
           ['adb', 'shell', 'rm', PROFILE_DEVICE_PATH], stdout=NULL)
 
   trace_to_text_output = subprocess.check_output(
-      [trace_to_text_binary, 'profile', PROFILE_LOCAL_PATH],
+      [trace_to_text_binary, 'profile',
+          os.path.join(profile_target, 'raw-trace')],
       env=os.environ)
   profile_path = None
   for word in trace_to_text_output.split():
@@ -407,30 +431,39 @@
     print_no_profile_error();
     return 1
 
+  for profile_file in profile_files:
+    shutil.copy(os.path.join(profile_path, profile_file), profile_target)
+
   subprocess.check_call(
       ['gzip'] +
-      [os.path.join(profile_path, x) for x in os.listdir(profile_path)])
+      [os.path.join(profile_target, x) for x in profile_files])
 
-  symlink_path = os.path.join(
-      os.path.dirname(profile_path), "heap_profile-latest")
-  if os.path.lexists(symlink_path):
-    os.unlink(symlink_path)
-  os.symlink(profile_path, symlink_path)
-  shutil.move(PROFILE_LOCAL_PATH, os.path.join(profile_path, 'raw-trace'))
+  symlink_path = None
+  if args.output is None:
+      symlink_path = os.path.join(
+          os.path.dirname(profile_target), "heap_profile-latest")
+      if os.path.lexists(symlink_path):
+        os.unlink(symlink_path)
+      os.symlink(profile_target, symlink_path)
 
   binary_path = os.getenv('PERFETTO_BINARY_PATH')
   if binary_path is not None:
       with open(os.path.join(profile_path, 'symbols'), 'w') as fd:
           ret = subprocess.call([
               trace_to_text_binary, 'symbolize',
-              os.path.join(profile_path, 'raw-trace')],
+              os.path.join(profile_target, 'raw-trace')],
               env=os.environ,
               stdout=fd)
           if ret != 0:
               print("Failed to symbolize. Continuing without symbols.",
                     file=sys.stderr)
 
-  print("Wrote profiles to {} (symlink {})".format(profile_path, symlink_path))
+  if symlink_path is not None:
+    print("Wrote profiles to {} (symlink {})".format(
+        profile_target, symlink_path))
+  else:
+    print("Wrote profiles to {}".format(profile_target))
+
   print("These can be viewed using pprof. Googlers: head to pprof/ and "
         "upload them.")