gt:     byte[][] parts = new byte[2][];
context: /**
   * Copyright (C) 2011 Whisper Systems
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package org.thoughtcrime.securesms.util;
  
  import android.annotation.SuppressLint;
  import android.annotation.TargetApi;
  import android.app.ActivityManager;
  import android.content.ClipData;
  import android.content.ClipboardManager;
  import android.content.Context;
  import android.content.pm.PackageManager;
  import android.graphics.Typeface;
  import android.os.Build;
  import android.os.Build.VERSION;
  import android.os.Build.VERSION_CODES;
  import android.os.Handler;
  import android.os.Looper;
  import android.provider.Telephony;
  import android.support.annotation.NonNull;
  import android.support.annotation.Nullable;
  import android.telephony.TelephonyManager;
  import android.text.Spannable;
  import android.text.SpannableString;
  import android.text.TextUtils;
  import android.text.style.StyleSpan;
  import android.util.Log;
  import android.widget.EditText;
  
  import com.google.i18n.phonenumbers.PhoneNumberUtil;
  
  import org.thoughtcrime.securesms.BuildConfig;
  import org.thoughtcrime.securesms.mms.OutgoingLegacyMmsConnection;
  import org.whispersystems.signalservice.api.util.InvalidNumberException;
  import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.io.UnsupportedEncodingException;
  import java.security.NoSuchAlgorithmException;
  import java.security.SecureRandom;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.concurrent.CountDownLatch;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.ThreadPoolExecutor;
  import java.util.concurrent.TimeUnit;
  
  import ws.com.google.android.mms.pdu.CharacterSets;
  import ws.com.google.android.mms.pdu.EncodedStringValue;
  
  public class Util {
    private static final String TAG = Util.class.getSimpleName();
  
    public static Handler handler = new Handler(Looper.getMainLooper());
  
    public static String join(String[] list, String delimiter) {
      return join(Arrays.asList(list), delimiter);
    }
  
    public static String join(Collection<String> list, String delimiter) {
      StringBuilder result = new StringBuilder();
      int i = 0;
  
      for (String item : list) {
        result.append(item);
  
        if (++i < list.size())
          result.append(delimiter);
      }
  
      return result.toString();
    }
  
    public static String join(long[] list, String delimeter) {
      StringBuilder sb = new StringBuilder();
  
      for (int j=0;j<list.length;j++) {
        if (j != 0) sb.append(delimeter);
        sb.append(list[j]);
      }
  
      return sb.toString();
    }
  
    public static ExecutorService newSingleThreadedLifoExecutor() {
      ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingLifoQueue<Runnable>());
  
      executor.execute(new Runnable() {
        @Override
        public void run() {
  //        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
          Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
        }
      });
  
      return executor;
    }
  
    public static boolean isEmpty(EncodedStringValue[] value) {
      return value == null || value.length == 0;
    }
  
    public static boolean isEmpty(EditText value) {
      return value == null || value.getText() == null || TextUtils.isEmpty(value.getText().toString());
    }
  
    public static CharSequence getBoldedString(String value) {
      SpannableString spanned = new SpannableString(value);
      spanned.setSpan(new StyleSpan(Typeface.BOLD), 0,
                      spanned.length(),
                      Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  
      return spanned;
    }
  
    public static @NonNull String toIsoString(byte[] bytes) {
      try {
        return new String(bytes, CharacterSets.MIMENAME_ISO_8859_1);
      } catch (UnsupportedEncodingException e) {
        throw new AssertionError("ISO_8859_1 must be supported!");
      }
    }
  
    public static byte[] toIsoBytes(String isoString) {
      try {
        return isoString.getBytes(CharacterSets.MIMENAME_ISO_8859_1);
      } catch (UnsupportedEncodingException e) {
        throw new AssertionError("ISO_8859_1 must be supported!");
      }
    }
  
    public static byte[] toUtf8Bytes(String utf8String) {
      try {
        return utf8String.getBytes(CharacterSets.MIMENAME_UTF_8);
      } catch (UnsupportedEncodingException e) {
        throw new AssertionError("UTF_8 must be supported!");
      }
    }
  
    public static void wait(Object lock, long timeout) {
      try {
        lock.wait(timeout);
      } catch (InterruptedException ie) {
        throw new AssertionError(ie);
      }
    }
  
    public static void close(OutputStream out) {
      try {
        out.close();
      } catch (IOException e) {
        Log.w(TAG, e);
      }
    }
  
    public static String canonicalizeNumber(Context context, String number)
        throws InvalidNumberException
    {
      String localNumber = TextSecurePreferences.getLocalNumber(context);
      return PhoneNumberFormatter.formatNumber(number, localNumber);
    }
  
    public static String canonicalizeNumberOrGroup(@NonNull Context context, @NonNull String number)
        throws InvalidNumberException
    {
      if (GroupUtil.isEncodedGroup(number)) return number;
      else                                  return canonicalizeNumber(context, number);
    }
  
    public static boolean isOwnNumber(Context context, String number) {
      try {
        String e164number = canonicalizeNumber(context, number);
        return TextSecurePreferences.getLocalNumber(context).equals(e164number);
      } catch (InvalidNumberException e) {
        Log.w(TAG, e);
      }
      return false;
    }
  
    public static byte[] readFully(InputStream in) throws IOException {
      ByteArrayOutputStream bout = new ByteArrayOutputStream();
      byte[] buffer              = new byte[4096];
      int read;
  
      while ((read = in.read(buffer)) != -1) {
        bout.write(buffer, 0, read);
      }
  
      in.close();
  
      return bout.toByteArray();
    }
  
    public static String readFullyAsString(InputStream in) throws IOException {
      return new String(readFully(in));
    }
  
    public static long copy(InputStream in, OutputStream out) throws IOException {
      byte[] buffer = new byte[4096];
      int read;
      long total = 0;
  
      while ((read = in.read(buffer)) != -1) {
        out.write(buffer, 0, read);
        total += read;
      }
  
      in.close();
      out.close();
  
      return total;
    }
  
    public static @Nullable String getDeviceE164Number(Context context) {
      final String  localNumber = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number();
      final String  countryIso  = getSimCountryIso(context);
      final Integer countryCode = PhoneNumberUtil.getInstance().getCountryCodeForRegion(countryIso);
  
      if (TextUtils.isEmpty(localNumber)) return null;
  
      if      (localNumber.startsWith("+"))    return localNumber;
      else if (!TextUtils.isEmpty(countryIso)) return PhoneNumberFormatter.formatE164(String.valueOf(countryCode), localNumber);
      else if (localNumber.length() == 10)     return "+1" + localNumber;
      else                                     return "+" + localNumber;
    }
  
    public static @Nullable String getSimCountryIso(Context context) {
      String simCountryIso = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getSimCountryIso();
      return simCountryIso != null ? simCountryIso.toUpperCase() : null;
    }
  
    public static <T> List<List<T>> partition(List<T> list, int partitionSize) {
      List<List<T>> results = new LinkedList<>();
  
      for (int index=0;index<list.size();index+=partitionSize) {
        int subListSize = Math.min(partitionSize, list.size() - index);
  
        results.add(list.subList(index, index + subListSize));
      }
  
      return results;
    }
  
    public static List<String> split(String source, String delimiter) {
      List<String> results = new LinkedList<>();
  
      if (TextUtils.isEmpty(source)) {
        return results;
      }
  
      String[] elements = source.split(delimiter);
      Collections.addAll(results, elements);
  
      return results;
    }
  
    public static byte[][] split(byte[] input, int firstLength, int secondLength) {
  