/**
   * Serialize a pattern.
   *
   * @param pattern The pattern.
   * @return The pattern in string form.
   */
  public static String patternToString(List<LockPatternView.Cell> pattern) {
    if (pattern == null) {
      return "";
    }
    final int patternSize = pattern.size();

    byte[] res = new byte[patternSize];
    for (int i = 0; i < patternSize; i++) {
      LockPatternView.Cell cell = pattern.get(i);
      res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
    }
    return new String(res);
  }
  /**
   * Deserialize a pattern.
   *
   * @param string The pattern serialized with {@link #patternToString}
   * @return The pattern.
   */
  public static List<LockPatternView.Cell> stringToPattern(String string) {
    List<LockPatternView.Cell> result = Lists.newArrayList();

    final byte[] bytes = string.getBytes();
    for (int i = 0; i < bytes.length; i++) {
      byte b = bytes[i];
      result.add(LockPatternView.Cell.of(b / 3, b % 3));
    }
    return result;
  }
  /*
   * Generate an SHA-1 hash for the pattern. Not the most secure, but it is
   * at least a second level of protection. First level is that the file
   * is in a location only readable by the system process.
   * @param pattern the gesture pattern.
   * @return the hash of the pattern in a byte array.
   */
  @MiuiHook(MiuiHookType.CHANGE_ACCESS)
  protected static byte[] patternToHash(List<LockPatternView.Cell> pattern) {
    if (pattern == null) {
      return null;
    }

    final int patternSize = pattern.size();
    byte[] res = new byte[patternSize];
    for (int i = 0; i < patternSize; i++) {
      LockPatternView.Cell cell = pattern.get(i);
      res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
    }
    try {
      MessageDigest md = MessageDigest.getInstance("SHA-1");
      byte[] hash = md.digest(res);
      return hash;
    } catch (NoSuchAlgorithmException nsa) {
      return res;
    }
  }