gt:                                 System.arraycopy(iv, 0, ivChange, 0, 32);
context: /*
   * This is the source code of Picca for Android.
   * It is licensed under GNU GPL v. 2 or later.
   * You should have received a copy of the license in this archive (see LICENSE).
   *
   * Author Nikolai Kudashov.
   */
  
  package com.roshin.gallery;
  
  import android.app.Activity;
  import android.content.SharedPreferences;
  
  import com.roshin.tgnet.ConnectionsManager;
  import com.roshin.tgnet.NativeByteBuffer;
  import com.roshin.tgnet.RequestDelegate;
  import com.roshin.tgnet.TLObject;
  import com.roshin.tgnet.TLRPC;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.math.BigInteger;
  import java.security.MessageDigest;
  import java.security.NoSuchAlgorithmException;
  import java.util.Locale;
  
  public class FileUploadOperation {
      private int uploadChunkSize = 1024 * 32;
      private String uploadingFilePath;
      public int state = 0;
      private byte[] readBuffer;
      public FileUploadOperationDelegate delegate;
      private int requestToken = 0;
      private int currentPartNum = 0;
      private long currentFileId;
      private boolean isLastPart = false;
      private long totalFileSize = 0;
      private int totalPartsCount = 0;
      private long currentUploaded = 0;
      private int saveInfoTimes = 0;
      private byte[] key;
      private byte[] iv;
      private byte[] ivChange;
      private boolean isEncrypted = false;
      private int fingerprint = 0;
      private boolean isBigFile = false;
      private String fileKey;
      private int estimatedSize = 0;
      private int uploadStartTime = 0;
      private FileInputStream stream;
      private MessageDigest mdEnc = null;
      private boolean started = false;
  
      public interface FileUploadOperationDelegate {
          void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv);
          void didFailedUploadingFile(FileUploadOperation operation);
          void didChangedUploadProgress(FileUploadOperation operation, float progress);
      }
  
      public FileUploadOperation(String location, boolean encrypted, int estimated) {
          uploadingFilePath = location;
          isEncrypted = encrypted;
          estimatedSize = estimated;
      }
  
      public long getTotalFileSize() {
          return totalFileSize;
      }
  
      public void start() {
          if (state != 0) {
              return;
          }
          state = 1;
          Utilities.stageQueue.postRunnable(new Runnable() {
              @Override
              public void run() {
                  startUploadRequest();
              }
          });
      }
  
      public void cancel() {
          if (state == 3) {
              return;
          }
          state = 2;
          if (requestToken != 0) {
              ConnectionsManager.getInstance().cancelRequest(requestToken, true);
          }
          delegate.didFailedUploadingFile(this);
          cleanup();
      }
  
      private void cleanup() {
          SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE);
          preferences.edit().remove(fileKey + "_time").
                  remove(fileKey + "_size").
                  remove(fileKey + "_uploaded").
                  remove(fileKey + "_id").
                  remove(fileKey + "_iv").
                  remove(fileKey + "_key").
                  remove(fileKey + "_ivc").commit();
          try {
              if (stream != null) {
                  stream.close();
                  stream = null;
              }
          } catch (Exception e) {
              FileLog.e("picca", e);
          }
      }
  
      protected void checkNewDataAvailable(final long finalSize) {
          Utilities.stageQueue.postRunnable(new Runnable() {
              @Override
              public void run() {
                  if (estimatedSize != 0 && finalSize != 0) {
                      estimatedSize = 0;
                      totalFileSize = finalSize;
                      totalPartsCount = (int) (totalFileSize + uploadChunkSize - 1) / uploadChunkSize;
                      if (started) {
                          SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE);
                          storeFileUploadInfo(preferences);
                      }
                  }
                  if (requestToken == 0) {
                      startUploadRequest();
                  }
              }
          });
      }
  
      private void storeFileUploadInfo(SharedPreferences preferences) {
          SharedPreferences.Editor editor = preferences.edit();
          editor.putInt(fileKey + "_time", uploadStartTime);
          editor.putLong(fileKey + "_size", totalFileSize);
          editor.putLong(fileKey + "_id", currentFileId);
          editor.remove(fileKey + "_uploaded");
          if (isEncrypted) {
              editor.putString(fileKey + "_iv", Utilities.bytesToHex(iv));
              editor.putString(fileKey + "_ivc", Utilities.bytesToHex(ivChange));
              editor.putString(fileKey + "_key", Utilities.bytesToHex(key));
          }
          editor.commit();
      }
  
      private void startUploadRequest() {
          if (state != 1) {
              return;
          }
  
          TLObject finalRequest;
  
          try {
              started = true;
              if (stream == null) {
                  File cacheFile = new File(uploadingFilePath);
                  stream = new FileInputStream(cacheFile);
                  if (estimatedSize != 0) {
                      totalFileSize = estimatedSize;
                  } else {
                      totalFileSize = cacheFile.length();
                  }
                  if (totalFileSize > 10 * 1024 * 1024) {
                      isBigFile = true;
                  } else {
                      try {
                          mdEnc = MessageDigest.getInstance("MD5");
                      } catch (NoSuchAlgorithmException e) {
                          FileLog.e("picca", e);
                      }
                  }
  
                  uploadChunkSize = (int) Math.max(32, (totalFileSize + 1024 * 3000 - 1) / (1024 * 3000));
                  if (1024 % uploadChunkSize != 0) {
                      int chunkSize = 64;
                      while (uploadChunkSize > chunkSize) {
                          chunkSize *= 2;
                      }
                      uploadChunkSize = chunkSize;
                  }
  
                  uploadChunkSize *= 1024;
                  totalPartsCount = (int) (totalFileSize + uploadChunkSize - 1) / uploadChunkSize;
                  readBuffer = new byte[uploadChunkSize];
  
                  fileKey = Utilities.MD5(uploadingFilePath + (isEncrypted ? "enc" : ""));
                  SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE);
                  long fileSize = preferences.getLong(fileKey + "_size", 0);
                  uploadStartTime = (int)(System.currentTimeMillis() / 1000);
                  boolean rewrite = false;
                  if (estimatedSize == 0 && fileSize == totalFileSize) {
                      currentFileId = preferences.getLong(fileKey + "_id", 0);
                      int date = preferences.getInt(fileKey + "_time", 0);
                      long uploadedSize = preferences.getLong(fileKey + "_uploaded", 0);
                      if (isEncrypted) {
                          String ivString = preferences.getString(fileKey + "_iv", null);
                          String keyString = preferences.getString(fileKey + "_key", null);
                          if (ivString != null && keyString != null) {
                              key = Utilities.hexToBytes(keyString);
                              iv = Utilities.hexToBytes(ivString);
                              if (key != null && iv != null && key.length == 32 && iv.length == 32) {
                                  ivChange = new byte[32];
  