private synchronized void generateParams(SchedullerPackage schedullerPackage) {
   schedullerPackage.messageId = generateMessageId();
   schedullerPackage.seqNo = generateSeqNo();
   schedullerPackage.idGenerationTime = getCurrentTime();
   schedullerPackage.relatedMessageIds.add(schedullerPackage.messageId);
   schedullerPackage.generatedMessageIds.add(schedullerPackage.messageId);
 }
 public void onMessageConfirmed(long msgId) {
   for (SchedullerPackage schedullerPackage :
       messages.values().toArray(new SchedullerPackage[0])) {
     if (schedullerPackage.state == STATE_SENT) {
       if (schedullerPackage.relatedMessageIds.contains(msgId)) {
         schedullerPackage.state = STATE_CONFIRMED;
       }
     }
   }
 }
 public void resendMessage(long msgId) {
   for (SchedullerPackage schedullerPackage :
       messages.values().toArray(new SchedullerPackage[0])) {
     if (schedullerPackage.relatedMessageIds.contains(msgId)) {
       // schedullerPackage.relatedMessageIds.clear();
       schedullerPackage.state = STATE_QUEUED;
       schedullerPackage.lastAttemptTime = 0;
     }
   }
 }
  private synchronized ArrayList<SchedullerPackage> actualPackages(int contextId) {
    ArrayList<SchedullerPackage> foundedPackages = new ArrayList<SchedullerPackage>();
    long time = getCurrentTime();
    for (SchedullerPackage schedullerPackage :
        messages.values().toArray(new SchedullerPackage[0])) {
      if (schedullerPackage.queuedToChannel != -1
          && contextId != schedullerPackage.queuedToChannel) {
        continue;
      }
      boolean isPendingPackage = false;

      if (schedullerPackage.ttlTime <= getCurrentTime()) {
        forgetMessage(schedullerPackage.id);
        continue;
      }

      if (schedullerPackage.state == STATE_QUEUED) {
        if (schedullerPackage.scheduleTime <= time) {
          isPendingPackage = true;
        }
      } else if (schedullerPackage.state == STATE_SENT) {
        if (getCurrentTime() <= schedullerPackage.expiresTime) {
          if (schedullerPackage.serialized == null
              || schedullerPackage.serialized.length < BIG_MESSAGE_SIZE) {
            if (getCurrentTime() - schedullerPackage.lastAttemptTime >= RETRY_TIMEOUT) {
              isPendingPackage = true;
            }
          }
        }
      }

      if (isPendingPackage) {
        if (schedullerPackage.serialized == null) {
          try {
            if (schedullerPackage.isRpc) {
              schedullerPackage.serialized =
                  wrapper.wrapObject((TLMethod) schedullerPackage.object).serialize();
            } else {
              schedullerPackage.serialized = schedullerPackage.object.serialize();
            }
          } catch (IOException e) {
            Logger.e(TAG, e);
            forgetMessage(schedullerPackage.id);
            continue;
          }
        }

        foundedPackages.add(schedullerPackage);
      }
    }
    return foundedPackages;
  }
 public void resetSession() {
   lastMessageId = 0;
   lastDependId = 0;
   seqNo = 0;
   currentMessageGeneration.clear();
   for (SchedullerPackage schedullerPackage :
       messages.values().toArray(new SchedullerPackage[0])) {
     schedullerPackage.idGenerationTime = 0;
     schedullerPackage.dependMessageId = 0;
     schedullerPackage.messageId = 0;
     schedullerPackage.seqNo = 0;
   }
 }
 public void unableToSendMessage(long messageId) {
   for (SchedullerPackage schedullerPackage :
       messages.values().toArray(new SchedullerPackage[0])) {
     if (schedullerPackage.state == STATE_SENT) {
       boolean contains = false;
       for (Long relatedMsgId : schedullerPackage.relatedMessageIds) {
         if (relatedMsgId == messageId) {
           contains = true;
           break;
         }
       }
       if (contains) {
         schedullerPackage.state = STATE_QUEUED;
       }
     }
   }
 }
 public void resendAsNewMessageDelayed(long msgId, int delay) {
   for (SchedullerPackage schedullerPackage :
       messages.values().toArray(new SchedullerPackage[0])) {
     if (schedullerPackage.relatedMessageIds.contains(msgId)) {
       schedullerPackage.idGenerationTime = 0;
       schedullerPackage.dependMessageId = 0;
       schedullerPackage.messageId = 0;
       schedullerPackage.seqNo = 0;
       schedullerPackage.state = STATE_QUEUED;
       schedullerPackage.scheduleTime = getCurrentTime() + delay;
       Logger.d(TAG, "Resending as new #" + schedullerPackage.id);
     }
   }
 }
  public synchronized PreparedPackage doSchedule(int contextId, boolean isInited) {
    ArrayList<SchedullerPackage> foundedPackages = actualPackages(contextId);

    synchronized (confirmedMessages) {
      if (foundedPackages.size() == 0
          && (confirmedMessages.size() <= MAX_ACK_COUNT
              || (System.nanoTime() - firstConfirmTime) < CONFIRM_TIMEOUT)) {
        return null;
      }
    }

    boolean useHighPriority = false;

    for (SchedullerPackage p : foundedPackages) {
      if (p.priority == PRIORITY_HIGH) {
        useHighPriority = true;
        break;
      }
    }

    ArrayList<SchedullerPackage> packages = new ArrayList<SchedullerPackage>();

    if (useHighPriority) {
      Logger.d("Scheduller", "Using high priority scheduling");
      int totalSize = 0;
      for (SchedullerPackage p : foundedPackages) {
        if (p.priority == PRIORITY_HIGH) {
          packages.add(p);
          totalSize += p.serialized.length;
          if (totalSize > MAX_WORKLOAD_SIZE) {
            break;
          }
        }
      }
    } else {
      int totalSize = 0;
      for (SchedullerPackage p : foundedPackages) {
        packages.add(p);
        Logger.d(
            "Scheduller", "Prepare package: " + p.supportTag + " of size " + p.serialized.length);
        totalSize += p.serialized.length;
        Logger.d("Scheduller", "Total size: " + totalSize);
        if (totalSize > MAX_WORKLOAD_SIZE) {
          break;
        }
      }
    }

    Logger.d(TAG, "Iteration: count: " + packages.size() + ", confirm:" + confirmedMessages.size());
    Logger.d(TAG, "Building package");
    if (foundedPackages.size() == 0 && confirmedMessages.size() != 0) {
      Long[] msgIds;
      synchronized (confirmedMessages) {
        msgIds = confirmedMessages.toArray(new Long[confirmedMessages.size()]);
        confirmedMessages.clear();
      }
      MTMsgsAck ack = new MTMsgsAck(msgIds);
      Logger.d(TAG, "Single msg_ack");
      try {
        return new PreparedPackage(
            generateSeqNoWeak(), generateMessageId(), ack.serialize(), useHighPriority);
      } catch (IOException e) {
        Logger.e(TAG, e);
        return null;
      }
    } else if (foundedPackages.size() == 1 && confirmedMessages.size() == 0) {
      SchedullerPackage schedullerPackage = foundedPackages.get(0);
      schedullerPackage.state = STATE_SENT;
      if (schedullerPackage.idGenerationTime == 0) {
        generateParams(schedullerPackage);
      }
      Logger.d(
          TAG,
          "Single package: #"
              + schedullerPackage.id
              + " "
              + schedullerPackage.supportTag
              + " ("
              + schedullerPackage.messageId
              + ", "
              + schedullerPackage.seqNo
              + ")");
      schedullerPackage.writtenToChannel = contextId;
      schedullerPackage.lastAttemptTime = getCurrentTime();
      return new PreparedPackage(
          schedullerPackage.seqNo,
          schedullerPackage.messageId,
          schedullerPackage.serialized,
          useHighPriority);
    } else {
      MTMessagesContainer container = new MTMessagesContainer();
      if ((confirmedMessages.size() > 0 && !useHighPriority) || (!isInited)) {
        try {
          Long[] msgIds;
          synchronized (confirmedMessages) {
            msgIds = confirmedMessages.toArray(new Long[0]);
            confirmedMessages.clear();
          }
          MTMsgsAck ack = new MTMsgsAck(msgIds);
          Logger.d(TAG, "Adding msg_ack: " + msgIds.length);
          container
              .getMessages()
              .add(new MTMessage(generateMessageId(), generateSeqNoWeak(), ack.serialize()));
        } catch (IOException e) {
          Logger.e(TAG, e);
        }
      }
      for (SchedullerPackage schedullerPackage : packages) {
        schedullerPackage.state = STATE_SENT;
        if (schedullerPackage.idGenerationTime == 0) {
          generateParams(schedullerPackage);
        }

        if (schedullerPackage.isDepend) {
          if (schedullerPackage.dependMessageId == 0) {
            if (lastDependId > 0) {
              schedullerPackage.dependMessageId = lastDependId;
            } else {
              schedullerPackage.dependMessageId = -1;
            }
          }

          lastDependId = schedullerPackage.messageId;
        }
        schedullerPackage.writtenToChannel = contextId;
        schedullerPackage.lastAttemptTime = getCurrentTime();
        if (schedullerPackage.isDepend && schedullerPackage.dependMessageId > 0) {

          Logger.d(
              TAG,
              "Adding package: #"
                  + schedullerPackage.id
                  + " "
                  + schedullerPackage.supportTag
                  + " ("
                  + schedullerPackage.messageId
                  + " on "
                  + schedullerPackage.dependMessageId
                  + ", "
                  + schedullerPackage.seqNo
                  + ")");

          MTInvokeAfter invokeAfter =
              new MTInvokeAfter(schedullerPackage.dependMessageId, schedullerPackage.serialized);
          try {
            container
                .getMessages()
                .add(
                    new MTMessage(
                        schedullerPackage.messageId,
                        schedullerPackage.seqNo,
                        invokeAfter.serialize()));
          } catch (IOException e) {
            Logger.e(TAG, e);
            // Never happens
          }
        } else {
          Logger.d(
              TAG,
              "Adding package: #"
                  + schedullerPackage.id
                  + " "
                  + schedullerPackage.supportTag
                  + " ("
                  + schedullerPackage.messageId
                  + ", "
                  + schedullerPackage.seqNo
                  + ")");
          container
              .getMessages()
              .add(
                  new MTMessage(
                      schedullerPackage.messageId,
                      schedullerPackage.seqNo,
                      schedullerPackage.serialized));
        }
      }

      long containerMessageId = generateMessageId();
      int containerSeq = generateSeqNoWeak();

      for (SchedullerPackage schedullerPackage : packages) {
        schedullerPackage.relatedMessageIds.add(containerMessageId);
      }

      Logger.d(TAG, "Sending Package (" + containerMessageId + ", " + containerSeq + ")");

      try {
        return new PreparedPackage(
            containerSeq, containerMessageId, container.serialize(), useHighPriority);
      } catch (IOException e) {
        // Might not happens
        Logger.e(TAG, e);
        return null;
      }
    }
  }
 public int postMessageDelayed(
     TLObject object,
     boolean isRpc,
     long timeout,
     int delay,
     int contextId,
     boolean highPrioroty) {
   int id = messagesIds.incrementAndGet();
   SchedullerPackage schedullerPackage = new SchedullerPackage(id);
   schedullerPackage.object = object;
   schedullerPackage.addTime = getCurrentTime();
   schedullerPackage.scheduleTime = schedullerPackage.addTime + delay;
   schedullerPackage.expiresTime = schedullerPackage.scheduleTime + timeout;
   schedullerPackage.ttlTime = schedullerPackage.scheduleTime + timeout * 2;
   schedullerPackage.isRpc = isRpc;
   schedullerPackage.queuedToChannel = contextId;
   schedullerPackage.priority = highPrioroty ? PRIORITY_HIGH : PRIORITY_NORMAL;
   schedullerPackage.isDepend = highPrioroty;
   schedullerPackage.supportTag = object.toString();
   messages.put(id, schedullerPackage);
   return id;
 }