/*
   * Check whether MIDlet-Heap-Size attribute is defined for the
   * MIDlet. It specifies maximum heap memory available for the MIDlet.
   *
   * The value is in bytes and must be a positive integer. The
   * only abbreviation in the value definition supported is K that
   * stands for kilobytes.
   *
   * If the amount declared exceeds the maximum heap limit allowed
   * for a single MIDlet, the attribute is ignored and the default
   * heap limit is used.
   *
   * Heap size is a total heap memory available for the isolate
   * where the MIDlet is launched. The size includes memory
   * occupied by the implementation for internal system purposes.
   * Thus the real heap size available for the MIDlet may be less.
   *
   * @param suiteId ID of an installed suite
   * @param midletName class name of MIDlet to invoke
   *
   * @return heap size limit if it's explicitly defined for the MIDlet,
   *         or -1 if it's not defined or invalid
   */
  private static int getMidletHeapSize(int suiteId, String midletName) {
    int heapSize = -1;

    if (Constants.EXTENDED_MIDLET_ATTRIBUTES_ENABLED) {
      String heapSizeProp =
          MIDletSuiteUtils.getSuiteProperty(suiteId, midletName, MIDletSuite.HEAP_SIZE_PROP);

      if (heapSizeProp != null) {
        boolean sizeInKilos = false;

        int propLen = heapSizeProp.length();
        if (propLen > 0) {
          char lastChar = heapSizeProp.charAt(propLen - 1);
          if ((lastChar == 'K') || (lastChar == 'k')) {
            heapSizeProp = heapSizeProp.substring(0, propLen - 1);
            sizeInKilos = true;
          }
        }

        try {
          heapSize = Integer.parseInt(heapSizeProp);
          heapSize = sizeInKilos ? heapSize * 1024 : heapSize;
        } catch (NumberFormatException e) {
          // ignore the attribute if the value is not valid
        }
      }
    }

    return heapSize;
  }
  /**
   * Starts a MIDlet in a new Isolate.
   *
   * @param midletSuiteStorage reference to a MIDletStorage object
   * @param externalAppId ID of MIDlet to invoke, given by an external application manager
   * @param id ID of an installed suite
   * @param midlet class name of MIDlet to invoke
   * @param displayName name to display to the user
   * @param arg0 if not null, this parameter will be available to the MIDlet as application property
   *     arg-0
   * @param arg1 if not null, this parameter will be available to the MIDlet as application property
   *     arg-1
   * @param arg2 if not null, this parameter will be available to the MIDlet as application property
   *     arg-2
   * @param memoryReserved the minimum amount of memory guaranteed to be available to the isolate at
   *     any time; < 0 if not used
   * @param memoryTotal the total amount of memory that the isolate can reserve; < 0 if not used
   * @param priority priority to set for the new isolate; <= 0 if not used
   * @param profileName name of the profile to set for the new isolate; null if not used
   * @param debugMode debug option for the MIDlet to be launched, one of: MIDP_NO_DEBUG,
   *     MIDP_DEBUG_SUSPEND, MIDP_DEBUG_NO_SUSPEND
   * @return false to signal that the MIDlet suite does not have to exit before the MIDlet is run
   */
  static boolean executeWithArgs(
      MIDletSuiteStorage midletSuiteStorage,
      int externalAppId,
      int id,
      String midlet,
      String displayName,
      String arg0,
      String arg1,
      String arg2,
      int memoryReserved,
      int memoryTotal,
      int priority,
      String profileName,
      int debugMode) {

    if (id == MIDletSuite.UNUSED_SUITE_ID) {
      // this was just a cancel request meant for SVM mode
      return false;
    }

    if (midlet == null) {
      throw new IllegalArgumentException("MIDlet class cannot be null");
    }

    if (!MIDletSuiteUtils.isAmsIsolate()) {
      /*
       * This is not the AMS isolate so send the request to the
       * AMS isolate.
       */
      midletExecuteEventProducer.sendMIDletExecuteEvent(
          externalAppId,
          id,
          midlet,
          displayName,
          arg0,
          arg1,
          arg2,
          memoryReserved,
          memoryTotal,
          priority,
          profileName,
          debugMode);
      return false;
    }

    // Don't start the MIDlet if it is already running.
    if (midletProxyList.isMidletInList(id, midlet)) {
      return false;
    }

    try {
      startMidletCommon(
          midletSuiteStorage,
          externalAppId,
          id,
          midlet,
          displayName,
          arg0,
          arg1,
          arg2,
          memoryReserved,
          memoryTotal,
          priority,
          profileName,
          debugMode);
    } catch (Throwable t) {
      /*
       * This method does not throw exceptions for start errors,
       * (just like the SVM case), for errors, MVM callers rely on
       * start error events.
       */
    }

    return false;
  }