15dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen/*
25dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen * Copyright (C) 2010 The Android Open Source Project
35dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen *
45dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen * Licensed under the Apache License, Version 2.0 (the "License");
55dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen * you may not use this file except in compliance with the License.
65dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen * You may obtain a copy of the License at
75dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen *
85dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen *      http://www.apache.org/licenses/LICENSE-2.0
95dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen *
105dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen * Unless required by applicable law or agreed to in writing, software
115dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen * distributed under the License is distributed on an "AS IS" BASIS,
125dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen * See the License for the specific language governing permissions and
145dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen * limitations under the License.
155dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen */
165dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
175dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenpackage android.os.storage;
185dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
195dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.content.Context;
205dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.content.res.Resources;
215dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.content.res.Resources.NotFoundException;
225dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.os.Environment;
235dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.os.SystemClock;
245dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.test.InstrumentationTestCase;
255dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.util.Log;
265dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.os.Environment;
275dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.os.FileUtils;
285dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.os.storage.OnObbStateChangeListener;
295dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport android.os.storage.StorageManager;
305dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
315dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport java.io.BufferedReader;
325dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport java.io.DataInputStream;
335dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport java.io.File;
345dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport java.io.FileInputStream;
355dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport java.io.FileNotFoundException;
365dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport java.io.FileReader;
375dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport java.io.InputStream;
385dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport java.io.IOException;
395dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenimport java.io.StringReader;
405dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
415dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyenpublic class StorageManagerBaseTest extends InstrumentationTestCase {
425dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
435dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected Context mContext = null;
445dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected StorageManager mSm = null;
455dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    private static String LOG_TAG = "StorageManagerBaseTest";
465dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static final long MAX_WAIT_TIME = 120*1000;
475dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static final long WAIT_TIME_INCR = 5*1000;
485dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_1 = "obb_file1.obb";
495dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_1_CONTENTS_1 = "OneToOneThousandInts.bin";
505dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_2 = "obb_file2.obb";
515dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_3 = "obb_file3.obb";
525dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_1_PASSWORD = "password1";
535dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_1_ENCRYPTED = "obb_enc_file100_orig1.obb";
545dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_2_UNSIGNED = "obb_file2_nosign.obb";
555dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_3_PASSWORD = "password3";
565dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_3_ENCRYPTED = "obb_enc_file100_orig3.obb";
575dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static String OBB_FILE_3_BAD_PACKAGENAME = "obb_file3_bad_packagename.obb";
585dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
595dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static boolean FORCE = true;
605dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected static boolean DONT_FORCE = false;
615dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
625dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    private static final String SAMPLE1_TEXT = "This is sample text.\n\nTesting 1 2 3.";
635dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
645dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    private static final String SAMPLE2_TEXT =
655dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        "We the people of the United States, in order to form a more perfect union,\n"
665dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        + "establish justice, insure domestic tranquility, provide for the common\n"
675dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        + "defense, promote the general welfare, and secure the blessings of liberty\n"
685dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        + "to ourselves and our posterity, do ordain and establish this Constitution\n"
695dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        + "for the United States of America.\n\n";
705dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
715dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    class MountingObbThread extends Thread {
725dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        boolean mStop = false;
735dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        volatile boolean mFileOpenOnObb = false;
745dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        private String mObbFilePath = null;
755dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        private String mPathToContentsFile = null;
765dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        private String mOfficialObbFilePath = null;
775dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
785dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        /**
795dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * Constructor
805dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *
815dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * @param obbFilePath path to the OBB image file
825dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * @param pathToContentsFile path to a file on the mounted OBB volume to open after the OBB
835dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *      has been mounted
845dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         */
855dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        public MountingObbThread (String obbFilePath, String pathToContentsFile) {
865dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertTrue("obbFilePath cannot be null!", obbFilePath != null);
875dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            mObbFilePath = obbFilePath;
885dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertTrue("path to contents file cannot be null!", pathToContentsFile != null);
895dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            mPathToContentsFile = pathToContentsFile;
905dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
915dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
925dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        /**
935dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * Runs the thread
945dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *
955dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * Mounts OBB_FILE_1, and tries to open a file on the mounted OBB (specified in the
965dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * constructor). Once it's open, it waits until someone calls its doStop(), after which it
975dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * closes the opened file.
985dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         */
995dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        public void run() {
1005dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            // the official OBB file path and the mount-request file path should be the same, but
1015dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            // let's distinguish the two as they may make for some interesting tests later
1025dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            mOfficialObbFilePath = mountObb(mObbFilePath);
1035dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertEquals("Expected and actual OBB file paths differ!", mObbFilePath,
1045dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    mOfficialObbFilePath);
1055dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1065dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            // open a file on OBB 1...
1075dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            DataInputStream inputFile = openFileOnMountedObb(mOfficialObbFilePath,
1085dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    mPathToContentsFile);
1095dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertTrue("Failed to open file!", inputFile != null);
1105dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1115dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            synchronized (this) {
1125dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                mFileOpenOnObb = true;
1135dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                notifyAll();
1145dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
1155dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1165dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            while (!mStop) {
1175dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                try {
1185dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    Thread.sleep(WAIT_TIME_INCR);
1195dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                } catch (InterruptedException e) {
1205dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    // nothing special to be done for interruptions
1215dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                }
1225dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
1235dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            try {
1245dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                inputFile.close();
1255dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            } catch (IOException e) {
1265dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                fail("Failed to close file on OBB due to error: " + e.toString());
1275dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
1285dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
1295dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1305dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        /**
1315dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * Tells whether a file has yet been successfully opened on the OBB or not
1325dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *
1335dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * @return true if the specified file on the OBB was opened; false otherwise
1345dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         */
1355dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        public boolean isFileOpenOnObb() {
1365dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return mFileOpenOnObb;
1375dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
1385dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1395dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        /**
1405dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * Returns the official path of the OBB file that was mounted
1415dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *
1425dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * This is not the mount path, but the normalized path to the actual OBB file
1435dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *
1445dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * @return a {@link String} representation of the path to the OBB file that was mounted
1455dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         */
1465dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        public String officialObbFilePath() {
1475dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return mOfficialObbFilePath;
1485dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
1495dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1505dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        /**
1515dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * Requests the thread to stop running
1525dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *
1535dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * Closes the opened file and returns
1545dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         */
1555dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        public void doStop() {
1565dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            mStop = true;
1575dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
1585dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
1595dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1605dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    public class ObbListener extends OnObbStateChangeListener {
1615dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        private String LOG_TAG = "StorageManagerBaseTest.ObbListener";
1625dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1635dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        String mOfficialPath = null;
1645dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        boolean mDone = false;
1655dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        int mState = -1;
1665dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1675dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        /**
1685dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * {@inheritDoc}
1695dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         */
1705dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        @Override
1715dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        public void onObbStateChange(String path, int state) {
1725dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            Log.i(LOG_TAG, "Storage state changing to: " + state);
1735dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1745dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            synchronized (this) {
1755dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                Log.i(LOG_TAG, "OfficialPath is now: " + path);
1765dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                mState = state;
1775dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                mOfficialPath = path;
1785dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                mDone = true;
1795dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                notifyAll();
1805dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
1815dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
1825dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1835dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        /**
1845dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * Tells whether we are done or not (system told us the OBB has changed state)
1855dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *
1865dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * @return true if the system has told us this OBB's state has changed, false otherwise
1875dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         */
1885dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        public boolean isDone() {
1895dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return mDone;
1905dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
1915dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
1925dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        /**
1935dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * The last state of the OBB, according to the system
1945dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *
1955dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * @return A {@link String} representation of the state of the OBB
1965dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         */
1975dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        public int state() {
1985dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return mState;
1995dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
2005dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2015dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        /**
2025dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * The normalized, official path to the OBB file (according to the system)
2035dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         *
2045dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         * @return A {@link String} representation of the official path to the OBB file
2055dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen         */
2065dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        public String officialPath() {
2075dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return mOfficialPath;
2085dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
2095dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
2105dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2115dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
2125dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * {@inheritDoc}
2135dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
2145dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    @Override
2155dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    public void setUp() throws Exception {
2165dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        mContext = getInstrumentation().getContext();
2175dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        mSm = (StorageManager)mContext.getSystemService(android.content.Context.STORAGE_SERVICE);
2185dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2195dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
2205dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2215dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
2225dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Helper to copy a raw resource file to an actual specified file
2235dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
2245dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param rawResId The raw resource ID of the OBB resource file
2255dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param outFile A File representing the file we want to copy the OBB to
2265dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @throws NotFoundException If the resource file could not be found
2275dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
2285dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    private void copyRawToFile(int rawResId, File outFile) throws NotFoundException {
2295dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        Resources res = mContext.getResources();
2305dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        InputStream is = null;
2315dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        try {
2325dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            is = res.openRawResource(rawResId);
2335dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } catch (NotFoundException e) {
2345dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            Log.i(LOG_TAG, "Failed to load resource with id: " + rawResId);
2355dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            throw e;
2365dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
2375dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
2385dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                | FileUtils.S_IRWXO, -1, -1);
2395dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue(FileUtils.copyToFile(is, outFile));
2405dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
2415dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                | FileUtils.S_IRWXO, -1, -1);
2425dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
2435dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2445dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
2455dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Creates an OBB file (with the given name), into the app's standard files directory
2465dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
2475dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param name The name of the OBB file we want to create/write to
2485dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param rawResId The raw resource ID of the OBB file in the package
2495dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @return A {@link File} representing the file to write to
2505dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
2515dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected File createObbFile(String name, int rawResId) {
2525dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        File outFile = null;
2535dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        try {
2545dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            final File filesDir = mContext.getFilesDir();
2555dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            outFile = new File(filesDir, name);
2565dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            copyRawToFile(rawResId, outFile);
2575dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } catch (NotFoundException e) {
2585dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            if (outFile != null) {
2595dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                outFile.delete();
2605dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
2615dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
2625dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        return outFile;
2635dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
2645dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2655dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
2665dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Mounts an OBB file and opens a file located on it
2675dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
2685dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param obbPath Path to OBB image
2695dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param fileName The full name and path to the file on the OBB to open once the OBB is mounted
2705dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @return The {@link DataInputStream} representing the opened file, if successful in opening
2715dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *      the file, or null of unsuccessful.
2725dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
2735dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected DataInputStream openFileOnMountedObb(String obbPath, String fileName) {
2745dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2755dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        // get mSm obb mount path
2765dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue("Cannot open file when OBB is not mounted!", mSm.isObbMounted(obbPath));
2775dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2785dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        String path = mSm.getMountedObbPath(obbPath);
2795dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue("Path should not be null!", path != null);
2805dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2815dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        File inFile = new File(path, fileName);
2825dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        DataInputStream inStream = null;
2835dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        try {
2845dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            inStream = new DataInputStream(new FileInputStream(inFile));
2855dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            Log.i(LOG_TAG, "Opened file: " + fileName + " for read at path: " + path);
2865dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } catch (FileNotFoundException e) {
2875dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            Log.e(LOG_TAG, e.toString());
2885dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return null;
2895dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } catch (SecurityException e) {
2905dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            Log.e(LOG_TAG, e.toString());
2915dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return null;
2925dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
2935dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        return inStream;
2945dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
2955dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
2965dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
2975dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Mounts an OBB file
2985dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
2995dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param obbFilePath The full path to the OBB file to mount
3005dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param key (optional) The key to use to unencrypt the OBB; pass null for no encryption
3015dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param expectedState The expected state resulting from trying to mount the OBB
3025dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @return A {@link String} representing the normalized path to OBB file that was mounted
3035dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
3045dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected String mountObb(String obbFilePath, String key, int expectedState) {
3055dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        return doMountObb(obbFilePath, key, expectedState);
3065dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
3075dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
3085dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
3095dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Mounts an OBB file with default options (no encryption, mounting succeeds)
3105dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
3115dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param obbFilePath The full path to the OBB file to mount
3125dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @return A {@link String} representing the normalized path to OBB file that was mounted
3135dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
3145dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected String mountObb(String obbFilePath) {
3155dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        return doMountObb(obbFilePath, null, OnObbStateChangeListener.MOUNTED);
3165dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
3175dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
3185dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
3195dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Synchronously waits for an OBB listener to be signaled of a state change, but does not throw
3205dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
3215dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param obbListener The listener for the OBB file
3225dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @return true if the listener was signaled of a state change by the system, else returns
3235dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *      false if we time out.
3245dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
3255dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected boolean doWaitForObbStateChange(ObbListener obbListener) {
3265dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        synchronized(obbListener) {
3275dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            long waitTimeMillis = 0;
3285dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            while (!obbListener.isDone()) {
3295dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                try {
3305dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    Log.i(LOG_TAG, "Waiting for listener...");
3315dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    obbListener.wait(WAIT_TIME_INCR);
3325dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    Log.i(LOG_TAG, "Awoke from waiting for listener...");
3335dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    waitTimeMillis += WAIT_TIME_INCR;
3345dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    if (waitTimeMillis > MAX_WAIT_TIME) {
3355dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                        fail("Timed out waiting for OBB state to change!");
3365dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    }
3375dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                } catch (InterruptedException e) {
3385dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    Log.i(LOG_TAG, e.toString());
3395dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                }
3405dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
3415dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return obbListener.isDone();
3425dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
3435dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
3445dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
3455dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
3465dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Synchronously waits for an OBB listener to be signaled of a state change
3475dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
3485dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param obbListener The listener for the OBB file
3495dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @return true if the listener was signaled of a state change by the system; else a fail()
3505dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *      is triggered if we timed out
3515dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
3525dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected String doMountObb_noThrow(String obbFilePath, String key, int expectedState) {
3535dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        Log.i(LOG_TAG, "doMountObb() on " + obbFilePath + " using key: " + key);
3545dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue ("Null path was passed in for OBB file!", obbFilePath != null);
3555dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue ("Null path was passed in for OBB file!", obbFilePath != null);
3565dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
3575dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        ObbListener obbListener = new ObbListener();
3585dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        boolean success = mSm.mountObb(obbFilePath, key, obbListener);
3595dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        success &= obbFilePath.equals(doWaitForObbStateChange(obbListener));
3605dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        success &= (expectedState == obbListener.state());
3615dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
3625dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        if (OnObbStateChangeListener.MOUNTED == expectedState) {
3635dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            success &= obbFilePath.equals(obbListener.officialPath());
3645dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            success &= mSm.isObbMounted(obbListener.officialPath());
3655dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } else {
3665dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            success &= !mSm.isObbMounted(obbListener.officialPath());
3675dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
3685dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
3695dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        if (success) {
3705dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return obbListener.officialPath();
3715dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } else {
3725dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            return null;
3735dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
3745dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
3755dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
3765dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
3775dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Mounts an OBB file without throwing and synchronously waits for it to finish mounting
3785dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
3795dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param obbFilePath The full path to the OBB file to mount
3805dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param key (optional) The key to use to unencrypt the OBB; pass null for no encryption
3815dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param expectedState The expected state resulting from trying to mount the OBB
3825dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @return A {@link String} representing the actual normalized path to OBB file that was
3835dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *      mounted, or null if the mounting failed
3845dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
3855dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected String doMountObb(String obbFilePath, String key, int expectedState) {
3865dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        Log.i(LOG_TAG, "doMountObb() on " + obbFilePath + " using key: " + key);
3875dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue ("Null path was passed in for OBB file!", obbFilePath != null);
3885dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
3895dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        ObbListener obbListener = new ObbListener();
3905dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue("mountObb call failed", mSm.mountObb(obbFilePath, key, obbListener));
3915dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue("Failed to get OBB mount status change for file: " + obbFilePath,
3925dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                doWaitForObbStateChange(obbListener));
3935dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertEquals("OBB mount state not what was expected!", expectedState, obbListener.state());
3945dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
3955dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        if (OnObbStateChangeListener.MOUNTED == expectedState) {
3965dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertEquals(obbFilePath, obbListener.officialPath());
3975dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertTrue("Obb should be mounted, but SM reports it is not!",
3985dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    mSm.isObbMounted(obbListener.officialPath()));
3995dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } else if (OnObbStateChangeListener.UNMOUNTED == expectedState) {
4005dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertFalse("Obb should not be mounted, but SM reports it is!",
4015dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    mSm.isObbMounted(obbListener.officialPath()));
4025dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
4035dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4045dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertEquals("Mount state is not what was expected!", expectedState, obbListener.state());
4055dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        return obbListener.officialPath();
4065dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
4075dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4085dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
4095dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Unmounts an OBB file without throwing, and synchronously waits for it to finish unmounting
4105dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
4115dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param obbFilePath The full path to the OBB file to mount
4125dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param force true if we shuold force the unmount, false otherwise
4135dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @return true if the unmount was successful, false otherwise
4145dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
4155dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected boolean unmountObb_noThrow(String obbFilePath, boolean force) {
4165dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        Log.i(LOG_TAG, "doUnmountObb_noThrow() on " + obbFilePath);
4175dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue ("Null path was passed in for OBB file!", obbFilePath != null);
4185dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        boolean success = true;
4195dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4205dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        ObbListener obbListener = new ObbListener();
4215dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue("unmountObb call failed", mSm.unmountObb(obbFilePath, force, obbListener));
4225dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4235dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        boolean stateChanged = doWaitForObbStateChange(obbListener);
4245dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        if (force) {
4255dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            success &= stateChanged;
4265dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            success &= (OnObbStateChangeListener.UNMOUNTED == obbListener.state());
4275dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            success &= !mSm.isObbMounted(obbFilePath);
4285dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
4295dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        return success;
4305dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
4315dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4325dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
4335dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Unmounts an OBB file and synchronously waits for it to finish unmounting
4345dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
4355dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param obbFilePath The full path to the OBB file to mount
4365dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param force true if we shuold force the unmount, false otherwise
4375dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
4385dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected void unmountObb(String obbFilePath, boolean force) {
4395dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        Log.i(LOG_TAG, "doUnmountObb() on " + obbFilePath);
4405dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue ("Null path was passed in for OBB file!", obbFilePath != null);
4415dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4425dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        ObbListener obbListener = new ObbListener();
4435dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue("unmountObb call failed", mSm.unmountObb(obbFilePath, force, obbListener));
4445dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4455dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        boolean stateChanged = doWaitForObbStateChange(obbListener);
4465dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        if (force) {
4475dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertTrue("Timed out waiting to unmount OBB file " + obbFilePath, stateChanged);
4485dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertEquals("OBB failed to unmount", OnObbStateChangeListener.UNMOUNTED,
4495dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    obbListener.state());
4505dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            assertFalse("Obb should NOT be mounted, but SM reports it is!", mSm.isObbMounted(
4515dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    obbFilePath));
4525dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
4535dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
4545dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4555dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
4565dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Helper to validate the contents of an "int" file in an OBB.
4575dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
4585dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * The format of the files are sequential int's, in the range of: [start..end)
4595dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
4605dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param path The full path to the file (path to OBB)
4615dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param filename The filename containing the ints to validate
4625dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param start The first int expected to be found in the file
4635dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param end The last int + 1 expected to be found in the file
4645dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
4655dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected void doValidateIntContents(String path, String filename, int start, int end) {
4665dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        File inFile = new File(path, filename);
4675dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        DataInputStream inStream = null;
4685dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        Log.i(LOG_TAG, "Validating file " + filename + " at " + path);
4695dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        try {
4705dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            inStream = new DataInputStream(new FileInputStream(inFile));
4715dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4725dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            for (int i = start; i < end; ++i) {
4735dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                if (inStream.readInt() != i) {
4745dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    fail("Unexpected value read in OBB file");
4755dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                }
4765dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
4775dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            if (inStream != null) {
4785dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                inStream.close();
4795dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
4805dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            Log.i(LOG_TAG, "Successfully validated file " + filename);
4815dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } catch (FileNotFoundException e) {
4825dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            fail("File " + inFile + " not found: " + e.toString());
4835dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } catch (IOException e) {
4845dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            fail("IOError with file " + inFile + ":" + e.toString());
4855dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
4865dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
4875dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
4885dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
4895dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Helper to validate the contents of a text file in an OBB
4905dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
4915dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param path The full path to the file (path to OBB)
4925dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param filename The filename containing the ints to validate
4935dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param contents A {@link String} containing the expected contents of the file
4945dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
4955dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected void doValidateTextContents(String path, String filename, String contents) {
4965dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        File inFile = new File(path, filename);
4975dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        BufferedReader fileReader = null;
4985dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        BufferedReader textReader = null;
4995dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        Log.i(LOG_TAG, "Validating file " + filename + " at " + path);
5005dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        try {
5015dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            fileReader = new BufferedReader(new FileReader(inFile));
5025dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            textReader = new BufferedReader(new StringReader(contents));
5035dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            String actual = null;
5045dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            String expected = null;
5055dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            while ((actual = fileReader.readLine()) != null) {
5065dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                expected = textReader.readLine();
5075dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                if (!actual.equals(expected)) {
5085dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    fail("File " + filename + " in OBB " + path + " does not match expected value");
5095dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                }
5105dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
5115dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            fileReader.close();
5125dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            textReader.close();
5135dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            Log.i(LOG_TAG, "File " + filename + " successfully verified.");
5145dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } catch (IOException e) {
5155dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            fail("IOError with file " + inFile + ":" + e.toString());
5165dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
5175dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
5185dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
5195dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
5205dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Helper to validate the contents of a "long" file on our OBBs
5215dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
5225dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * The format of the files are sequential 0's of type long
5235dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
5245dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param path The full path to the file (path to OBB)
5255dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param filename The filename containing the ints to validate
5265dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param size The number of zero's expected in the file
5275dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param checkContents If true, the contents of the file are actually verified; if false,
5285dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *      we simply verify that the file can be opened
5295dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
5305dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected void doValidateZeroLongFile(String path, String filename, long size,
5315dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            boolean checkContents) {
5325dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        File inFile = new File(path, filename);
5335dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        DataInputStream inStream = null;
5345dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        Log.i(LOG_TAG, "Validating file " + filename + " at " + path);
5355dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        try {
5365dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            inStream = new DataInputStream(new FileInputStream(inFile));
5375dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
5385dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            if (checkContents) {
5395dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                for (long i = 0; i < size; ++i) {
5405dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    if (inStream.readLong() != 0) {
5415dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                        fail("Unexpected value read in OBB file" + filename);
5425dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    }
5435dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                }
5445dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
5455dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
5465dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            if (inStream != null) {
5475dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                inStream.close();
5485dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
5495dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            Log.i(LOG_TAG, "File " + filename + " successfully verified for " + size + " zeros");
5505dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        } catch (IOException e) {
5515dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            fail("IOError with file " + inFile + ":" + e.toString());
5525dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
5535dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
5545dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
5555dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
5565dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Helper to synchronously wait until we can get a path for a given OBB file
5575dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
5585dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param filePath The full normalized path to the OBB file
5595dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @return The mounted path of the OBB, used to access contents in it
5605dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
5615dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected String doWaitForPath(String filePath) {
5625dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        String path = null;
5635dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
5645dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        long waitTimeMillis = 0;
5655dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        assertTrue("OBB " + filePath + " is not currently mounted!", mSm.isObbMounted(filePath));
5665dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        while (path == null) {
5675dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            try {
5685dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                Thread.sleep(WAIT_TIME_INCR);
5695dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                waitTimeMillis += WAIT_TIME_INCR;
5705dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                if (waitTimeMillis > MAX_WAIT_TIME) {
5715dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                    fail("Timed out waiting to get path of OBB file " + filePath);
5725dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                }
5735dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            } catch (InterruptedException e) {
5745dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                // do nothing
5755dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            }
5765dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen            path = mSm.getMountedObbPath(filePath);
5775dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        }
5785dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        Log.i(LOG_TAG, "Got OBB path: " + path);
5795dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        return path;
5805dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
5815dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
5825dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
5835dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Verifies the pre-defined contents of our first OBB (OBB_FILE_1)
5845dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
5855dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * The OBB contains 4 files and no subdirectories
5865dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
5875dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param filePath The normalized path to the already-mounted OBB file
5885dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
5895dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected void verifyObb1Contents(String filePath) {
5905dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        String path = null;
5915dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        path = doWaitForPath(filePath);
5925dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
5935dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        // Validate contents of 2 files in this obb
5945dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateIntContents(path, "OneToOneThousandInts.bin", 0, 1000);
5955dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateIntContents(path, "SevenHundredInts.bin", 0, 700);
5965dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateZeroLongFile(path, "FiveLongs.bin", 5, true);
5975dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
5985dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
5995dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
6005dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Verifies the pre-defined contents of our second OBB (OBB_FILE_2)
6015dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
6025dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * The OBB contains 2 files and no subdirectories
6035dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
6045dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param filePath The normalized path to the already-mounted OBB file
6055dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
6065dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected void verifyObb2Contents(String filename) {
6075dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        String path = null;
6085dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        path = doWaitForPath(filename);
6095dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
6105dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        // Validate contents of file
6115dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateTextContents(path, "sample.txt", SAMPLE1_TEXT);
6125dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateTextContents(path, "sample2.txt", SAMPLE2_TEXT);
6135dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
6145dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
6155dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    /**
6165dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * Verifies the pre-defined contents of our third OBB (OBB_FILE_3)
6175dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
6185dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * The OBB contains nested files and subdirectories
6195dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     *
6205dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     * @param filePath The normalized path to the already-mounted OBB file
6215dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen     */
6225dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    protected void verifyObb3Contents(String filename) {
6235dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        String path = null;
6245dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        path = doWaitForPath(filename);
6255dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
6265dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        // Validate contents of file
6275dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateIntContents(path, "OneToOneThousandInts.bin", 0, 1000);
6285dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateZeroLongFile(path, "TwoHundredLongs", 200, true);
6295dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
6305dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        // validate subdirectory 1
6315dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateZeroLongFile(path + File.separator + "subdir1", "FiftyLongs", 50, true);
6325dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
6335dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        // validate subdirectory subdir2/
6345dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateIntContents(path + File.separator + "subdir2", "OneToOneThousandInts", 0, 1000);
6355dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
6365dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        // validate subdirectory subdir2/subdir2a/
6375dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateZeroLongFile(path + File.separator + "subdir2" + File.separator + "subdir2a",
6385dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                "TwoHundredLongs", 200, true);
6395dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen
6405dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        // validate subdirectory subdir2/subdir2a/subdir2a1/
6415dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen        doValidateIntContents(path + File.separator + "subdir2" + File.separator + "subdir2a"
6425dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen                + File.separator + "subdir2a1", "OneToOneThousandInts", 0, 1000);
6435dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen    }
6445dda76a72e8bb4630fb5fd38a42e7bceb5b9c954Neal Nguyen}