Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e232b99 authored by Jack Yu's avatar Jack Yu
Browse files

Fixed out of memory when running telephony unit tests

1. Temporarily increased the heap size so the unit tests can use more
   than 192MB of memory.
2. Enabled strict mode in TelephonyTest to detect resource leaks.
3. Fixed the resource leaks in carrier resolver and emergency number
   tracker.
4. Fixed the resource leak in InboundSmsTrackerTest.
5. Temporarily disabled EmergencyNumberTrackerTest and
   ImsRttTextHandlerTest, which caused resource leaks after enabling
   strict mode.

Bug: 221655014
Test: acloud create && atest FrameworksTelephonyTests
Change-Id: Ib8e37aa5b62e56f246063f820a848c3373965b72
parent 17537464
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -962,12 +962,14 @@ public class CarrierResolver extends Handler {
    public int getCarrierListVersion() {
        // Use the cached value if it exists, otherwise retrieve it.
        if (mCarrierListVersion == null) {
            final Cursor cursor = mContext.getContentResolver().query(
            // The auto closeable cursor will be closed after exiting try-block.
            try (Cursor cursor = mContext.getContentResolver().query(
                    Uri.withAppendedPath(CarrierId.All.CONTENT_URI,
                    "get_version"), null, null, null);
                    "get_version"), null, null, null)) {
                cursor.moveToFirst();
                mCarrierListVersion = cursor.getInt(0);
            }
        }
        return mCarrierListVersion;
    }

+29 −52
Original line number Diff line number Diff line
@@ -450,17 +450,16 @@ public class EmergencyNumberTracker extends Handler {
    }

    private void cacheEmergencyDatabaseByCountry(String countryIso) {
        BufferedInputStream inputStream = null;
        ProtobufEccData.AllInfo allEccMessages = null;
        int assetsDatabaseVersion = INVALID_DATABASE_VERSION;
        int assetsDatabaseVersion;

        // Read the Asset emergency number database
        List<EmergencyNumber> updatedAssetEmergencyNumberList = new ArrayList<>();
        try {
            inputStream = new BufferedInputStream(
        // try-with-resource. The 2 streams are auto closeable.
        try (BufferedInputStream inputStream = new BufferedInputStream(
                mPhone.getContext().getAssets().open(EMERGENCY_NUMBER_DB_ASSETS_FILE));
            allEccMessages = ProtobufEccData.AllInfo.parseFrom(readInputStreamToByteArray(
                    new GZIPInputStream(inputStream)));
             GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream)) {
            ProtobufEccData.AllInfo allEccMessages = ProtobufEccData.AllInfo.parseFrom(
                    readInputStreamToByteArray(gzipInputStream));
            assetsDatabaseVersion = allEccMessages.revision;
            logd(countryIso + " asset emergency database is loaded. Ver: " + assetsDatabaseVersion
                    + " Phone Id: " + mPhone.getPhoneId());
@@ -475,16 +474,7 @@ public class EmergencyNumberTracker extends Handler {
            EmergencyNumber.mergeSameNumbersInEmergencyNumberList(updatedAssetEmergencyNumberList);
        } catch (IOException ex) {
            logw("Cache asset emergency database failure: " + ex);
        } finally {
            // close quietly by catching non-runtime exceptions.
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (RuntimeException rethrown) {
                    throw rethrown;
                } catch (Exception ignored) {
                }
            }
            return;
        }

        // Cache OTA emergency number database
@@ -494,7 +484,6 @@ public class EmergencyNumberTracker extends Handler {
        if (otaDatabaseVersion == INVALID_DATABASE_VERSION
                && assetsDatabaseVersion == INVALID_DATABASE_VERSION) {
            loge("No database available. Phone Id: " + mPhone.getPhoneId());
            return;
        } else if (assetsDatabaseVersion > otaDatabaseVersion) {
            logd("Using Asset Emergency database. Version: " + assetsDatabaseVersion);
            mCurrentDatabaseVersion = assetsDatabaseVersion;
@@ -505,27 +494,32 @@ public class EmergencyNumberTracker extends Handler {
    }

    private int cacheOtaEmergencyNumberDatabase() {
        FileInputStream fileInputStream = null;
        BufferedInputStream inputStream = null;
        ProtobufEccData.AllInfo allEccMessages = null;
        int otaDatabaseVersion = INVALID_DATABASE_VERSION;

        // Read the OTA emergency number database
        List<EmergencyNumber> updatedOtaEmergencyNumberList = new ArrayList<>();
        try {

        File file;
        // If OTA File partition is not available, try to reload the default one.
        if (mOverridedOtaDbParcelFileDescriptor == null) {
                fileInputStream = new FileInputStream(
                        new File(Environment.getDataDirectory(),
                                EMERGENCY_NUMBER_DB_OTA_FILE_PATH));
            file = new File(Environment.getDataDirectory(), EMERGENCY_NUMBER_DB_OTA_FILE_PATH);
        } else {
                File file = ParcelFileDescriptor
                        .getFile(mOverridedOtaDbParcelFileDescriptor.getFileDescriptor());
                fileInputStream = new FileInputStream(new File(file.getAbsolutePath()));
            try {
                file = ParcelFileDescriptor.getFile(mOverridedOtaDbParcelFileDescriptor
                        .getFileDescriptor()).getAbsoluteFile();
            } catch (IOException ex) {
                loge("Cache ota emergency database IOException: " + ex);
                return INVALID_DATABASE_VERSION;
            }
        }
            inputStream = new BufferedInputStream(fileInputStream);
            allEccMessages = ProtobufEccData.AllInfo.parseFrom(readInputStreamToByteArray(
                    new GZIPInputStream(inputStream)));

        // try-with-resource. Those 3 streams are all auto closeable.
        try (FileInputStream fileInputStream = new FileInputStream(file);
             BufferedInputStream inputStream = new BufferedInputStream(fileInputStream);
             GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream)) {
            allEccMessages = ProtobufEccData.AllInfo.parseFrom(
                    readInputStreamToByteArray(gzipInputStream));
            String countryIso = getLastKnownEmergencyCountryIso();
            logd(countryIso + " ota emergency database is loaded. Ver: " + otaDatabaseVersion);
            otaDatabaseVersion = allEccMessages.revision;
@@ -540,24 +534,7 @@ public class EmergencyNumberTracker extends Handler {
            EmergencyNumber.mergeSameNumbersInEmergencyNumberList(updatedOtaEmergencyNumberList);
        } catch (IOException ex) {
            loge("Cache ota emergency database IOException: " + ex);
        } finally {
            // Close quietly by catching non-runtime exceptions.
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (RuntimeException rethrown) {
                    throw rethrown;
                } catch (Exception ignored) {
                }
            }
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (RuntimeException rethrown) {
                    throw rethrown;
                } catch (Exception ignored) {
                }
            }
            return INVALID_DATABASE_VERSION;
        }

        // Use a valid database that has higher version.
+2 −1
Original line number Diff line number Diff line
@@ -17,7 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.frameworks.telephonytests">

    <application android:name="com.android.internal.telephony.TestApplication">
    <application android:name="com.android.internal.telephony.TestApplication"
        android:largeHeap="true">
        <uses-library android:name="android.test.runner"/>
        <activity android:label="TelephonyTest"
             android:name="TelephonyTest"
+4 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.database.Cursor;
import android.database.MatrixCursor;
import android.test.suitebuilder.annotation.SmallTest;

@@ -100,8 +101,10 @@ public class InboundSmsTrackerTest {
    @Test
    @SmallTest
    public void testInitializationFromDb() {
        Cursor cursor = createFakeCursor();
        mInboundSmsTracker = new InboundSmsTracker(InstrumentationRegistry.getContext(),
                createFakeCursor(), false);
                cursor, false);
        cursor.close();
        testInitialization();
    }
}
 No newline at end of file
+17 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import android.os.Message;
import android.os.MessageQueue;
import android.os.RegistrantList;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.UserManager;
import android.permission.LegacyPermissionManager;
import android.provider.BlockedNumberContract;
@@ -483,8 +484,24 @@ public abstract class TelephonyTest {
        mOldInstances.clear();
    }

    // TODO: Unit tests that do not extend TelephonyTest or ImsTestBase should enable strict mode
    //   by calling this method.
    public static void enableStrictMode() {
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedSqlLiteObjects()
                .detectLeakedClosableObjects()
                .detectIncorrectContextUse()
                .detectLeakedRegistrationObjects()
                .detectUnsafeIntentLaunch()
                .detectActivityLeaks()
                .penaltyLog()
                .penaltyDeath()
                .build());
    }

    protected void setUp(String tag) throws Exception {
        TAG = tag;
        enableStrictMode();
        MockitoAnnotations.initMocks(this);
        TelephonyManager.disableServiceHandleCaching();
        SubscriptionController.disableCaching();
Loading