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

Commit 0cb370ba authored by Shoki Inoka's avatar Shoki Inoka Committed by takeshi tanigawa
Browse files

Startup WAP PUSH service before handling SMS messages

SMS message handling which has been received while the device is locked
starts just after unlocking the device. Then WAP PUSH service may not
finish starting and WAP PUSH SMS message may not be processed.

To resolve the problem, enable to bind WapPushManager during DirectBoot
and ensures that SMS messages are processed when unlocked. And change
the storage of database used by WapPushManager to support DirectBoot.

Test: manual - Confirm that WapPushOverSms#onServiceConnected() is
called during DirectBoot.
Confirm that WapPushManager#WapPushManager() is called when unlocking
the screen.
Test: auto - Passed WapPushTest#testDataBaseMigration.
Bug: 141654363

Change-Id: I3eebfea6a6da920f9aca674073c2cd3563cbd658
parent deeefd7b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@

    <original-package android:name="com.android.smspush" />
    <application
        android:allowClearUserData="false">
        android:allowClearUserData="false"
        android:directBootAware="true">
        <service android:name=".WapPushManager"
            android:permission="com.android.smspush.WAPPUSH_MANAGER_BIND"
            android:exported="true">
+95 −36
Original line number Diff line number Diff line
@@ -26,17 +26,21 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserManager;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IWapPushManager;
import com.android.internal.telephony.WapPushManagerParams;

import java.io.File;

/**
 * The WapPushManager service is implemented to process incoming
 * WAP Push messages and to maintain the Receiver Application/Application
@@ -67,8 +71,13 @@ public class WapPushManager extends Service {
    /**
     * Inner class that deals with application ID table
     */
    private class WapPushManDBHelper extends SQLiteOpenHelper {
        WapPushManDBHelper(Context context) {
    @VisibleForTesting
    public static class WapPushManDBHelper extends SQLiteOpenHelper {
        /**
         * Constructor
         */
        @VisibleForTesting
        public WapPushManDBHelper(Context context) {
            super(context, DATABASE_NAME, null, WAP_PUSH_MANAGER_VERSION);
            if (LOCAL_LOGV) Log.v(LOG_TAG, "helper instance created.");
        }
@@ -269,10 +278,6 @@ public class WapPushManager extends Service {
                int app_type, boolean need_signature, boolean further_processing) {
            WapPushManDBHelper dbh = getDatabase(mContext);
            SQLiteDatabase db = dbh.getWritableDatabase();
            WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, x_app_id, content_type);
            boolean ret = false;
            boolean insert = false;
            int sq = 0;

            if (!appTypeCheck(app_type)) {
                Log.w(LOG_TAG, "invalid app_type " + app_type + ". app_type must be "
@@ -280,34 +285,8 @@ public class WapPushManager extends Service {
                        + WapPushManagerParams.APP_TYPE_SERVICE);
                return false;
            }

            if (lastapp == null) {
                insert = true;
                sq = 0;
            } else if (!lastapp.packageName.equals(package_name) ||
                    !lastapp.className.equals(class_name)) {
                insert = true;
                sq = lastapp.installOrder + 1;
            }

            if (insert) {
                ContentValues values = new ContentValues();

                values.put("x_wap_application", x_app_id);
                values.put("content_type", content_type);
                values.put("package_name", package_name);
                values.put("class_name", class_name);
                values.put("app_type", app_type);
                values.put("need_signature", need_signature ? 1 : 0);
                values.put("further_processing", further_processing ? 1 : 0);
                values.put("install_order", sq);
                db.insert(APPID_TABLE_NAME, null, values);
                if (LOCAL_LOGV) Log.v(LOG_TAG, "add:" + x_app_id + ":" + content_type
                        + " " + package_name + "." + class_name
                        + ", newsq:" + sq);
                ret = true;
            }

            boolean ret = insertPackage(dbh, db, x_app_id, content_type, package_name, class_name,
                    app_type, need_signature, further_processing);
            db.close();

            return ret;
@@ -404,11 +383,91 @@ public class WapPushManager extends Service {
    protected WapPushManDBHelper getDatabase(Context context) {
        if (mDbHelper == null) {
            if (LOCAL_LOGV) Log.v(LOG_TAG, "create new db inst.");
            mDbHelper = new WapPushManDBHelper(context);
            mDbHelper = new WapPushManDBHelper(context.createDeviceProtectedStorageContext());
        }
        // Migrate existing legacy database into the device encrypted storage.
        migrateWapPushManDBIfNeeded(context);
        return mDbHelper;
    }

    /**
     * Inserts a package information into a database
     */
    @VisibleForTesting
    public boolean insertPackage(WapPushManDBHelper dbh, SQLiteDatabase db, String appId,
            String contentType, String packageName, String className, int appType,
            boolean needSignature, boolean furtherProcessing) {

        WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, appId, contentType);
        boolean insert = false;
        int sq = 0;

        if (lastapp == null) {
            insert = true;
            sq = 0;
        } else if (!lastapp.packageName.equals(packageName)
                || !lastapp.className.equals(className)) {
            insert = true;
            sq = lastapp.installOrder + 1;
        }

        if (insert) {
            ContentValues values = new ContentValues();

            values.put("x_wap_application", appId);
            values.put("content_type", contentType);
            values.put("package_name", packageName);
            values.put("class_name", className);
            values.put("app_type", appType);
            values.put("need_signature", needSignature ? 1 : 0);
            values.put("further_processing", furtherProcessing ? 1 : 0);
            values.put("install_order", sq);
            db.insert(APPID_TABLE_NAME, null, values);
            if (LOCAL_LOGV) {
                Log.v(LOG_TAG, "add:" + appId + ":" + contentType + " " + packageName
                        + "." + className + ", newsq:" + sq);
            }
            return true;
        }
        return false;
    }

    /**
     * Migrates a legacy database into the device encrypted storage
     */
    private void migrateWapPushManDBIfNeeded(Context context) {
        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
        File file = context.getDatabasePath(DATABASE_NAME);
        if (!userManager.isUserUnlocked() || !file.exists()) {
            // Check if the device is unlocked because a legacy database can't access during
            // DirectBoot.
            return;
        }

        // Migration steps below:
        // 1. Merge the package info to legacy database if there is any package info which is
        // registered during DirectBoot.
        // 2. Move the data base to the device encryped storage.
        WapPushManDBHelper legacyDbHelper = new WapPushManDBHelper(context);
        SQLiteDatabase legacyDb = legacyDbHelper.getWritableDatabase();
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        Cursor cur = db.query(APPID_TABLE_NAME, null, null, null, null, null, null);
        while (cur.moveToNext()) {
            insertPackage(legacyDbHelper, legacyDb,
                    cur.getString(cur.getColumnIndex("x_wap_application")),
                    cur.getString(cur.getColumnIndex("content_type")),
                    cur.getString(cur.getColumnIndex("package_name")),
                    cur.getString(cur.getColumnIndex("class_name")),
                    cur.getInt(cur.getColumnIndex("app_type")),
                    cur.getInt(cur.getColumnIndex("need_signature")) == 1,
                    cur.getInt(cur.getColumnIndex("further_processing")) == 1);
        }
        cur.close();
        legacyDb.close();
        db.close();
        context.createDeviceProtectedStorageContext().moveDatabaseFrom(context, DATABASE_NAME);
        Log.i(LOG_TAG, "Migrated the legacy database.");
    }

    /**
     * This method is used for testing
+51 −6
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.sqlite.SQLiteDatabase;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Telephony.Sms.Intents;
@@ -33,7 +34,9 @@ import com.android.internal.telephony.WspTypeDecoder;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.util.HexDump;
import com.android.smspush.WapPushManager;
import com.android.smspush.WapPushManager.WapPushManDBHelper;

import java.io.File;
import java.util.Random;

/**
@@ -467,8 +470,9 @@ public class WapPushTest extends ServiceTestCase<WapPushManager> {
        try {
            super.setUp();
            // get verifier
            getContext().bindService(new Intent(IDataVerify.class.getName()),
                    mConn, Context.BIND_AUTO_CREATE);
            Intent intent = new Intent(IDataVerify.class.getName());
            intent.setPackage("com.android.smspush.unitTests");
            getContext().bindService(intent, mConn, Context.BIND_AUTO_CREATE);
        } catch (Exception e) {
            Log.w(LOG_TAG, "super exception");
        }
@@ -552,15 +556,15 @@ public class WapPushTest extends ServiceTestCase<WapPushManager> {
    }

    /**
     * Add sqlite injection test
     * Sqlite injection test
     */
    public void testAddPackage0() {
    public void testSqliteInjection() {
        String inject = "' union select 0,'com.android.settings','com.android.settings.Settings',0,0,0--";

        // insert new data
        // update data
        IWapPushManager iwapman = getInterface();
        try {
            assertFalse(iwapman.addPackage(
            assertFalse(iwapman.updatePackage(
                    inject,
                    Integer.toString(mContentTypeValue),
                    mPackageName, mClassName,
@@ -2528,4 +2532,45 @@ public class WapPushTest extends ServiceTestCase<WapPushManager> {
        mMessageBody = originalMessageBody;
    }

    /**
     * DataBase migration test.
     */
    public void testDataBaseMigration() {
        IWapPushManager iwapman = getInterface();
        WapPushManager wpman = getService();
        Context context = getContext();

        addPackageToLegacyDB(mAppIdValue, mContentTypeValue, mPackageName, mClassName,
                WapPushManagerParams.APP_TYPE_SERVICE, true, true);
        addPackageToLegacyDB(mAppIdValue + 10, mContentTypeValue, mPackageName, mClassName,
                WapPushManagerParams.APP_TYPE_SERVICE, true, true);

        File oldDbFile = context.getDatabasePath("wappush.db");
        assertTrue(oldDbFile.exists());
        assertTrue(wpman.verifyData(Integer.toString(mAppIdValue),
                Integer.toString(mContentTypeValue),
                mPackageName, mClassName,
                WapPushManagerParams.APP_TYPE_SERVICE, true, true));
        assertFalse(oldDbFile.exists());

        // Clean up DB
        try {
            iwapman.deletePackage(Integer.toString(mAppIdValue),
                    Integer.toString(mContentTypeValue), mPackageName, mClassName);
            iwapman.deletePackage(Integer.toString(mAppIdValue + 10),
                    Integer.toString(mContentTypeValue), mPackageName, mClassName);
        } catch (RemoteException e) {
            assertTrue(false);
        }
    }

    private void addPackageToLegacyDB(int appId, int contextType, String packagename,
            String classnName, int appType, boolean signature, boolean furtherProcessing) {
        WapPushManager wpman = getService();
        WapPushManDBHelper dbh = new WapPushManDBHelper(getContext());
        SQLiteDatabase db = dbh.getWritableDatabase();

        wpman.insertPackage(dbh, db, Integer.toString(appId), Integer.toString(contextType),
                packagename, classnName, appType, signature, furtherProcessing);
    }
}