1f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa/* 2f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * Copyright (C) 2007-2014 The Android Open Source Project 3f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 4f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * use this file except in compliance with the License. You may obtain a copy of 6f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * the License at 7f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 8f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * http://www.apache.org/licenses/LICENSE-2.0 9f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 10f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * Unless required by applicable law or agreed to in writing, software 11f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * License for the specific language governing permissions and limitations under 14f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * the License. 15f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa */ 16f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 17f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawapackage android.view.inputmethod; 18f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 19f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawaimport android.os.Parcel; 20f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawaimport android.util.Slog; 21f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 22f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawaimport java.io.ByteArrayInputStream; 23f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawaimport java.io.ByteArrayOutputStream; 24f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawaimport java.util.List; 25f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawaimport java.util.zip.GZIPInputStream; 26f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawaimport java.util.zip.GZIPOutputStream; 27f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 28f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa/** 29f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * An array-like container that stores multiple instances of {@link InputMethodSubtype}. 30f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 31f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * <p>This container is designed to reduce the risk of {@link TransactionTooLargeException} 32f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * when one or more instancess of {@link InputMethodInfo} are transferred through IPC. 33f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * Basically this class does following three tasks.</p> 34f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * <ul> 35f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * <li>Applying compression for the marshalled data</li> 36f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * <li>Lazily unmarshalling objects</li> 37f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * <li>Caching the marshalled data when appropriate</li> 38f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * </ul> 39f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 40f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * @hide 41f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa */ 42f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawapublic class InputMethodSubtypeArray { 43f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private final static String TAG = "InputMethodSubtypeArray"; 44f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 45f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa /** 46f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * Create a new instance of {@link InputMethodSubtypeArray} from an existing list of 47f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * {@link InputMethodSubtype}. 48f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 49f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * @param subtypes A list of {@link InputMethodSubtype} from which 50f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * {@link InputMethodSubtypeArray} will be created. 51f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa */ 52f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa public InputMethodSubtypeArray(final List<InputMethodSubtype> subtypes) { 53f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (subtypes == null) { 54f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mCount = 0; 55f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return; 56f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 57f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mCount = subtypes.size(); 58f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mInstance = subtypes.toArray(new InputMethodSubtype[mCount]); 59f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 60f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 61f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa /** 62f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * Unmarshall an instance of {@link InputMethodSubtypeArray} from a given {@link Parcel} 63f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * object. 64f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 65f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * @param source A {@link Parcel} object from which {@link InputMethodSubtypeArray} will be 66f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * unmarshalled. 67f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa */ 68f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa public InputMethodSubtypeArray(final Parcel source) { 69f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mCount = source.readInt(); 70f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (mCount > 0) { 71f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mDecompressedSize = source.readInt(); 72f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mCompressedData = source.createByteArray(); 73f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 74f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 75f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 76f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa /** 77f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * Marshall the instance into a given {@link Parcel} object. 78f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 79f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * <p>This methods may take a bit additional time to compress data lazily when called 80f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * first time.</p> 81f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 82f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * @param source A {@link Parcel} object to which {@link InputMethodSubtypeArray} will be 83f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * marshalled. 84f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa */ 85f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa public void writeToParcel(final Parcel dest) { 86f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (mCount == 0) { 87f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa dest.writeInt(mCount); 88f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return; 89f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 90f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 91f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa byte[] compressedData = mCompressedData; 92f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa int decompressedSize = mDecompressedSize; 93f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (compressedData == null && decompressedSize == 0) { 94f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa synchronized (mLockObject) { 95f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa compressedData = mCompressedData; 96f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa decompressedSize = mDecompressedSize; 97f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (compressedData == null && decompressedSize == 0) { 98f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa final byte[] decompressedData = marshall(mInstance); 99f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa compressedData = compress(decompressedData); 100f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (compressedData == null) { 101f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa decompressedSize = -1; 102f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa Slog.i(TAG, "Failed to compress data."); 103f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } else { 104f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa decompressedSize = decompressedData.length; 105f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 106f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mDecompressedSize = decompressedSize; 107f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mCompressedData = compressedData; 108f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 109f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 110f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 111f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 112f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (compressedData != null && decompressedSize > 0) { 113f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa dest.writeInt(mCount); 114f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa dest.writeInt(decompressedSize); 115f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa dest.writeByteArray(compressedData); 116f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } else { 117f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa Slog.i(TAG, "Unexpected state. Behaving as an empty array."); 118f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa dest.writeInt(0); 119f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 120f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 121f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 122f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa /** 123f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * Return {@link InputMethodSubtype} specified with the given index. 124f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 125f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * <p>This methods may take a bit additional time to decompress data lazily when called 126f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * first time.</p> 127f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * 128f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * @param index The index of {@link InputMethodSubtype}. 129f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa */ 130f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa public InputMethodSubtype get(final int index) { 131f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (index < 0 || mCount <= index) { 132f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa throw new ArrayIndexOutOfBoundsException(); 133f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 134f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa InputMethodSubtype[] instance = mInstance; 135f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (instance == null) { 136f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa synchronized (mLockObject) { 137f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa instance = mInstance; 138f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (instance == null) { 139f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa final byte[] decompressedData = 140f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa decompress(mCompressedData, mDecompressedSize); 141f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa // Clear the compressed data until {@link #getMarshalled()} is called. 142f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mCompressedData = null; 143f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mDecompressedSize = 0; 144f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (decompressedData != null) { 145f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa instance = unmarshall(decompressedData); 146f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } else { 147f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa Slog.e(TAG, "Failed to decompress data. Returns null as fallback."); 148f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa instance = new InputMethodSubtype[mCount]; 149f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 150f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa mInstance = instance; 151f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 152f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 153f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 154f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return instance[index]; 155f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 156f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 157f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa /** 158f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa * Return the number of {@link InputMethodSubtype} objects. 159f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa */ 160f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa public int getCount() { 161f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return mCount; 162f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 163f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 164f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private final Object mLockObject = new Object(); 165f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private final int mCount; 166f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 167f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private volatile InputMethodSubtype[] mInstance; 168f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private volatile byte[] mCompressedData; 169f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private volatile int mDecompressedSize; 170f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 171f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private static byte[] marshall(final InputMethodSubtype[] array) { 172f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa Parcel parcel = null; 173f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa try { 174f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa parcel = Parcel.obtain(); 175f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa parcel.writeTypedArray(array, 0); 176f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return parcel.marshall(); 177f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } finally { 178f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (parcel != null) { 179f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa parcel.recycle(); 180f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa parcel = null; 181f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 182f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 183f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 184f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 185f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private static InputMethodSubtype[] unmarshall(final byte[] data) { 186f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa Parcel parcel = null; 187f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa try { 188f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa parcel = Parcel.obtain(); 189f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa parcel.unmarshall(data, 0, data.length); 190f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa parcel.setDataPosition(0); 191f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return parcel.createTypedArray(InputMethodSubtype.CREATOR); 192f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } finally { 193f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (parcel != null) { 194f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa parcel.recycle(); 195f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa parcel = null; 196f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 197f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 198f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 199f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 200f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private static byte[] compress(final byte[] data) { 201a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa try (final ByteArrayOutputStream resultStream = new ByteArrayOutputStream(); 202a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa final GZIPOutputStream zipper = new GZIPOutputStream(resultStream)) { 203f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa zipper.write(data); 204a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa zipper.finish(); 205a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa return resultStream.toByteArray(); 206a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa } catch(Exception e) { 207a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa Slog.e(TAG, "Failed to compress the data.", e); 208f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return null; 209f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 210f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 211f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa 212f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa private static byte[] decompress(final byte[] data, final int expectedSize) { 213a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa try (final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); 214a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa final GZIPInputStream unzipper = new GZIPInputStream(inputStream)) { 215f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa final byte [] result = new byte[expectedSize]; 216f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa int totalReadBytes = 0; 217f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa while (totalReadBytes < result.length) { 218f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa final int restBytes = result.length - totalReadBytes; 219f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa final int readBytes = unzipper.read(result, totalReadBytes, restBytes); 220f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (readBytes < 0) { 221f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa break; 222f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 223f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa totalReadBytes += readBytes; 224f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 225f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa if (expectedSize != totalReadBytes) { 226f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return null; 227f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 228f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return result; 229a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa } catch(Exception e) { 230a1d49337fb3ff4b336cddb1198658778b0e8949bYohei Yukawa Slog.e(TAG, "Failed to decompress the data.", e); 231f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa return null; 232f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 233f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa } 234f06569561fe1c6e898debf8bb9f37331a9f87323Yohei Yukawa} 235