/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.preload;

import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
import com.android.preload.classdataretrieval.hprof.Hprof;
import com.android.ddmlib.DdmPreferences;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.IShellOutputReceiver;

import java.util.Date;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * Helper class for some device routines.
 */
public class DeviceUtils {

  public static void init(int debugPort) {
    DdmPreferences.setSelectedDebugPort(debugPort);

    Hprof.init();

    AndroidDebugBridge.init(true);

    AndroidDebugBridge.createBridge();
  }

  /**
   * Run a command in the shell on the device.
   */
  public static void doShell(IDevice device, String cmdline, long timeout, TimeUnit unit) {
    doShell(device, cmdline, new NullShellOutputReceiver(), timeout, unit);
  }

  /**
   * Run a command in the shell on the device. Collects and returns the console output.
   */
  public static String doShellReturnString(IDevice device, String cmdline, long timeout,
      TimeUnit unit) {
    CollectStringShellOutputReceiver rec = new CollectStringShellOutputReceiver();
    doShell(device, cmdline, rec, timeout, unit);
    return rec.toString();
  }

  /**
   * Run a command in the shell on the device, directing all output to the given receiver.
   */
  public static void doShell(IDevice device, String cmdline, IShellOutputReceiver receiver,
      long timeout, TimeUnit unit) {
    try {
      device.executeShellCommand(cmdline, receiver, timeout, unit);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * Run am start on the device.
   */
  public static void doAMStart(IDevice device, String name, String activity) {
    doShell(device, "am start -n " + name + " /." + activity, 30, TimeUnit.SECONDS);
  }

  /**
   * Find the device with the given serial. Give up after the given timeout (in milliseconds).
   */
  public static IDevice findDevice(String serial, int timeout) {
    WaitForDevice wfd = new WaitForDevice(serial, timeout);
    return wfd.get();
  }

  /**
   * Get all devices ddms knows about. Wait at most for the given timeout.
   */
  public static IDevice[] findDevices(int timeout) {
    WaitForDevice wfd = new WaitForDevice(null, timeout);
    wfd.get();
    return AndroidDebugBridge.getBridge().getDevices();
  }

  /**
   * Return the build type of the given device. This is the value of the "ro.build.type"
   * system property.
   */
  public static String getBuildType(IDevice device) {
    try {
      Future<String> buildType = device.getSystemProperty("ro.build.type");
      return buildType.get(500, TimeUnit.MILLISECONDS);
    } catch (Exception e) {
    }
    return null;
  }

  /**
   * Check whether the given device has a pre-optimized boot image. More precisely, checks
   * whether /system/framework/ * /boot.art exists.
   */
  public static boolean hasPrebuiltBootImage(IDevice device) {
    String ret =
        doShellReturnString(device, "ls /system/framework/*/boot.art", 500, TimeUnit.MILLISECONDS);

    return !ret.contains("No such file or directory");
  }

  /**
   * Remove files involved in a standard build that interfere with collecting data. This will
   * remove /etc/preloaded-classes, which determines which classes are allocated already in the
   * boot image. It also deletes any compiled boot image on the device. Then it restarts the
   * device.
   *
   * This is a potentially long-running operation, as the boot after the deletion may take a while.
   * The method will abort after the given timeout.
   */
  public static boolean removePreloaded(IDevice device, long preloadedWaitTimeInSeconds) {
    String oldContent =
        DeviceUtils.doShellReturnString(device, "cat /etc/preloaded-classes", 1, TimeUnit.SECONDS);
    if (oldContent.trim().equals("")) {
      System.out.println("Preloaded-classes already empty.");
      return true;
    }

    // Stop the system server etc.
    doShell(device, "stop", 100, TimeUnit.MILLISECONDS);

    // Remount /system, delete /etc/preloaded-classes. It would be nice to use "adb remount,"
    // but AndroidDebugBridge doesn't expose it.
    doShell(device, "mount -o remount,rw /system", 500, TimeUnit.MILLISECONDS);
    doShell(device, "rm /etc/preloaded-classes", 100, TimeUnit.MILLISECONDS);
    // We do need an empty file.
    doShell(device, "touch /etc/preloaded-classes", 100, TimeUnit.MILLISECONDS);

    // Delete the files in the dalvik cache.
    doShell(device, "rm /data/dalvik-cache/*/*boot.art", 500, TimeUnit.MILLISECONDS);

    // We'll try to use dev.bootcomplete to know when the system server is back up. But stop
    // doesn't reset it, so do it manually.
    doShell(device, "setprop dev.bootcomplete \"0\"", 500, TimeUnit.MILLISECONDS);

    // Start the system server.
    doShell(device, "start", 100, TimeUnit.MILLISECONDS);

    // Do a loop checking each second whether bootcomplete. Wait for at most the given
    // threshold.
    Date startDate = new Date();
    for (;;) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        // Ignore spurious wakeup.
      }
      // Check whether bootcomplete.
      String ret =
          doShellReturnString(device, "getprop dev.bootcomplete", 500, TimeUnit.MILLISECONDS);
      if (ret.trim().equals("1")) {
        break;
      }
      System.out.println("Still not booted: " + ret);

      // Check whether we timed out. This is a simplistic check that doesn't take into account
      // things like switches in time.
      Date endDate = new Date();
      long seconds =
          TimeUnit.SECONDS.convert(endDate.getTime() - startDate.getTime(), TimeUnit.MILLISECONDS);
      if (seconds > preloadedWaitTimeInSeconds) {
        return false;
      }
    }

    return true;
  }

  /**
   * Enable method-tracing on device. The system should be restarted after this.
   */
  public static void enableTracing(IDevice device) {
    // Disable selinux.
    doShell(device, "setenforce 0", 100, TimeUnit.MILLISECONDS);

    // Make the profile directory world-writable.
    doShell(device, "chmod 777 /data/dalvik-cache/profiles", 100, TimeUnit.MILLISECONDS);

    // Enable streaming method tracing with a small 1K buffer.
    doShell(device, "setprop dalvik.vm.method-trace true", 100, TimeUnit.MILLISECONDS);
    doShell(device, "setprop dalvik.vm.method-trace-file "
                    + "/data/dalvik-cache/profiles/zygote.trace.bin", 100, TimeUnit.MILLISECONDS);
    doShell(device, "setprop dalvik.vm.method-trace-file-siz 1024", 100, TimeUnit.MILLISECONDS);
    doShell(device, "setprop dalvik.vm.method-trace-stream true", 100, TimeUnit.MILLISECONDS);
  }

  private static class NullShellOutputReceiver implements IShellOutputReceiver {
    @Override
    public boolean isCancelled() {
      return false;
    }

    @Override
    public void flush() {}

    @Override
    public void addOutput(byte[] arg0, int arg1, int arg2) {}
  }

  private static class CollectStringShellOutputReceiver implements IShellOutputReceiver {

    private StringBuilder builder = new StringBuilder();

    @Override
    public String toString() {
      String ret = builder.toString();
      // Strip trailing newlines. They are especially ugly because adb uses DOS line endings.
      while (ret.endsWith("\r") || ret.endsWith("\n")) {
        ret = ret.substring(0, ret.length() - 1);
      }
      return ret;
    }

    @Override
    public void addOutput(byte[] arg0, int arg1, int arg2) {
      builder.append(new String(arg0, arg1, arg2));
    }

    @Override
    public void flush() {}

    @Override
    public boolean isCancelled() {
      return false;
    }
  }

  private static class WaitForDevice {

    private String serial;
    private long timeout;
    private IDevice device;

    public WaitForDevice(String serial, long timeout) {
      this.serial = serial;
      this.timeout = timeout;
      device = null;
    }

    public IDevice get() {
      if (device == null) {
          WaitForDeviceListener wfdl = new WaitForDeviceListener(serial);
          synchronized (wfdl) {
              AndroidDebugBridge.addDeviceChangeListener(wfdl);

              // Check whether we already know about this device.
              IDevice[] devices = AndroidDebugBridge.getBridge().getDevices();
              if (serial != null) {
                  for (IDevice d : devices) {
                      if (serial.equals(d.getSerialNumber())) {
                          // Only accept if there are clients already. Else wait for the callback informing
                          // us that we now have clients.
                          if (d.hasClients()) {
                              device = d;
                          }

                          break;
                      }
                  }
              } else {
                  if (devices.length > 0) {
                      device = devices[0];
                  }
              }

              if (device == null) {
                  try {
                      wfdl.wait(timeout);
                  } catch (InterruptedException e) {
                      // Ignore spurious wakeups.
                  }
                  device = wfdl.getDevice();
              }

              AndroidDebugBridge.removeDeviceChangeListener(wfdl);
          }
      }

      if (device != null) {
          // Wait for clients.
          WaitForClientsListener wfcl = new WaitForClientsListener(device);
          synchronized (wfcl) {
              AndroidDebugBridge.addDeviceChangeListener(wfcl);

              if (!device.hasClients()) {
                  try {
                      wfcl.wait(timeout);
                  } catch (InterruptedException e) {
                      // Ignore spurious wakeups.
                  }
              }

              AndroidDebugBridge.removeDeviceChangeListener(wfcl);
          }
      }

      return device;
    }

    private static class WaitForDeviceListener implements IDeviceChangeListener {

        private String serial;
        private IDevice device;

        public WaitForDeviceListener(String serial) {
            this.serial = serial;
        }

        public IDevice getDevice() {
            return device;
        }

        @Override
        public void deviceChanged(IDevice arg0, int arg1) {
            // We may get a device changed instead of connected. Handle like a connection.
            deviceConnected(arg0);
        }

        @Override
        public void deviceConnected(IDevice arg0) {
            if (device != null) {
                // Ignore updates.
                return;
            }

            if (serial == null || serial.equals(arg0.getSerialNumber())) {
                device = arg0;
                synchronized (this) {
                    notifyAll();
                }
            }
        }

        @Override
        public void deviceDisconnected(IDevice arg0) {
            // Ignore disconnects.
        }

    }

    private static class WaitForClientsListener implements IDeviceChangeListener {

        private IDevice myDevice;

        public WaitForClientsListener(IDevice myDevice) {
            this.myDevice = myDevice;
        }

        @Override
        public void deviceChanged(IDevice arg0, int arg1) {
            if (arg0 == myDevice && (arg1 & IDevice.CHANGE_CLIENT_LIST) != 0) {
                // Got a client list, done here.
                synchronized (this) {
                    notifyAll();
                }
            }
        }

        @Override
        public void deviceConnected(IDevice arg0) {
        }

        @Override
        public void deviceDisconnected(IDevice arg0) {
        }

    }
  }

}
