org.thoughtland.xlocation.UpdateService.java Source code

Java tutorial

Introduction

Here is the source code for org.thoughtland.xlocation.UpdateService.java

Source

package org.thoughtland.xlocation;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

public class UpdateService extends Service {
    public static final String cAction = "Action";
    public static final int cActionBoot = 1;
    public static final int cActionUpdated = 2;
    public static final String cFlush = "org.thoughtland.xlocation.action.FLUSH";
    public static final String cUpdate = "org.thoughtland.xlocation.action.UPDATE";

    private static Thread mWorkerThread;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Check if work
        if (intent == null) {
            stopSelf();
            return 0;
        }

        // Flush
        if (cFlush.equals(intent.getAction())) {
            try {
                PrivacyService.getClient().flush();
            } catch (Throwable ex) {
                Util.bug(null, ex);
            }
            stopSelf();
            return 0;
        }

        // Update
        if (cUpdate.equals(intent.getAction())) {
            if (Util.hasProLicense(this) != null) {
                int userId = Util.getUserId(Process.myUid());
                boolean updates = PrivacyManager.getSettingBool(userId, PrivacyManager.cSettingUpdates, false);
                if (updates)
                    new ActivityShare.UpdateTask(this).execute();
            }
            stopSelf();
            return 0;
        }

        // Check action
        Bundle extras = intent.getExtras();
        if (extras.containsKey(cAction)) {
            final int action = extras.getInt(cAction);
            Util.log(null, Log.WARN, "Service received action=" + action + " flags=" + flags);

            // Check service
            if (PrivacyService.getClient() == null) {
                Util.log(null, Log.ERROR, "Service not available");
                stopSelf();
                return 0;
            }

            // Start foreground service
            NotificationCompat.Builder builder = new NotificationCompat.Builder(UpdateService.this);
            builder.setSmallIcon(R.drawable.ic_launcher);
            builder.setContentTitle(getString(R.string.app_name));
            builder.setContentText(getString(R.string.msg_service));
            builder.setWhen(System.currentTimeMillis());
            builder.setAutoCancel(false);
            builder.setOngoing(true);
            Notification notification = builder.build();
            startForeground(Util.NOTIFY_SERVICE, notification);

            // Start worker
            mWorkerThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        // Check action
                        if (action == cActionBoot) {
                            // Boot received
                            migrate(UpdateService.this);
                            upgrade(UpdateService.this);
                            randomize(UpdateService.this);

                        } else if (action == cActionUpdated) {
                            // Self updated
                            upgrade(UpdateService.this);

                        } else
                            Util.log(null, Log.ERROR, "Unknown action=" + action);

                        // Done
                        stopForeground(true);
                        stopSelf();
                    } catch (Throwable ex) {
                        Util.bug(null, ex);
                        // Leave service running
                    }
                }

            });
            mWorkerThread.start();
        } else
            Util.log(null, Log.ERROR, "Action missing");

        return START_STICKY;
    }

    private static void migrate(Context context) throws IOException, RemoteException {
        int first = 0;
        String format = context.getString(R.string.msg_migrating);
        List<ApplicationInfo> listApp = context.getPackageManager().getInstalledApplications(0);

        // Start migrate
        PrivacyProvider.migrateLegacy(context);

        // Migrate global settings
        PrivacyManager.setSettingList(PrivacyProvider.migrateSettings(context, 0));
        PrivacyProvider.finishMigrateSettings(0);

        // Migrate application settings/restrictions
        for (int i = 1; i <= listApp.size(); i++) {
            int uid = listApp.get(i - 1).uid;
            // Settings
            List<PSetting> listSetting = PrivacyProvider.migrateSettings(context, uid);
            PrivacyManager.setSettingList(listSetting);
            PrivacyProvider.finishMigrateSettings(uid);

            // Restrictions
            List<PRestriction> listRestriction = PrivacyProvider.migrateRestrictions(context, uid);
            PrivacyManager.setRestrictionList(listRestriction);
            PrivacyProvider.finishMigrateRestrictions(uid);

            if (first == 0)
                if (listSetting.size() > 0 || listRestriction.size() > 0)
                    first = i;
            if (first > 0 && first < listApp.size())
                notifyProgress(context, Util.NOTIFY_MIGRATE, format, 100 * (i - first) / (listApp.size() - first));
        }
        if (first == 0)
            Util.log(null, Log.WARN, "Nothing to migrate");

        // Complete migration
        int userId = Util.getUserId(Process.myUid());
        PrivacyService.getClient()
                .setSetting(new PSetting(userId, "", PrivacyManager.cSettingMigrated, Boolean.toString(true)));
    }

    private static void upgrade(Context context) throws NameNotFoundException {
        // Get previous version number
        int userId = Util.getUserId(Process.myUid());
        Version currentVersion = new Version(Util.getSelfVersionName(context));
        Version storedVersion = new Version(
                PrivacyManager.getSetting(userId, PrivacyManager.cSettingVersion, "0.0"));
        boolean dangerous = PrivacyManager.getSettingBool(userId, PrivacyManager.cSettingDangerous, false);

        // Check if upgrade needed
        if (storedVersion.compareTo(new Version("0.0")) != 0 && currentVersion.compareTo(storedVersion) > 0) {
            Util.log(null, Log.WARN, "Starting upgrade from version " + storedVersion + " to version "
                    + currentVersion + " dangerous=" + dangerous);

            // Upgrade packages
            int first = 0;
            String format = context.getString(R.string.msg_upgrading);
            List<ApplicationInfo> listApp = context.getPackageManager().getInstalledApplications(0);

            for (int i = 1; i <= listApp.size(); i++) {
                int uid = listApp.get(i - 1).uid;
                List<PRestriction> listRestriction = getUpgradeWork(storedVersion, uid, dangerous);
                PrivacyManager.setRestrictionList(listRestriction);

                // Reset on demand for system applications
                if (new ApplicationInfoEx(context, listApp.get(i - 1).uid).isSystem())
                    if (storedVersion.compareTo(new Version("2.0.38")) < 0)
                        if (PrivacyManager.getSettingBool(listApp.get(i - 1).uid, PrivacyManager.cSettingOnDemand,
                                false)) {
                            Util.log(null, Log.WARN, "Disabling on demand for uid=" + listApp.get(i - 1).uid);
                            PrivacyManager.setSetting(listApp.get(i - 1).uid, PrivacyManager.cSettingOnDemand,
                                    null);
                        }

                if (first == 0)
                    if (listRestriction.size() > 0)
                        first = i;
                if (first > 0 && first < listApp.size())
                    notifyProgress(context, Util.NOTIFY_UPGRADE, format,
                            100 * (i - first) / (listApp.size() - first));
            }
            if (first == 0)
                Util.log(null, Log.WARN,
                        "Nothing to upgrade from version " + storedVersion + " to " + currentVersion);

            // Remove legacy setting
            if (dangerous)
                PrivacyManager.setSetting(userId, PrivacyManager.cSettingDangerous, null);

            // Resolve quirk
            if (storedVersion.compareTo(new Version("2.99.28")) < 0)
                if (!PrivacyManager.getSettingBool(0, PrivacyManager.cSettingNoResolve, false)) {
                    Util.log(null, Log.WARN, "Enabling quirk resolve");
                    PrivacyManager.setSetting(0, PrivacyManager.cSettingResolve, Boolean.toString(true));
                }

            // Wipe template
            if (storedVersion.compareTo(new Version("2.0.34")) < 0)
                for (PSetting setting : PrivacyManager.getSettingList(0, null))
                    if (Meta.cTypeTemplate.equals(setting.type)) {
                        Util.log(null, Log.WARN, "Deleting " + setting);
                        PrivacyManager.setSetting(setting.uid, setting.type, setting.name, null);
                    }
        } else
            Util.log(null, Log.WARN, "No upgrade from version " + storedVersion + " to " + currentVersion);

        // Set new version number
        if (currentVersion.compareTo(storedVersion) > 0)
            PrivacyManager.setSetting(userId, PrivacyManager.cSettingVersion, currentVersion.toString());

        // Cleanup
        PrivacyManager.removeLegacySalt(userId);
    }

    private static void randomize(Context context) {
        int first = 0;
        String format = context.getString(R.string.msg_randomizing);
        List<ApplicationInfo> listApp = context.getPackageManager().getInstalledApplications(0);

        // Randomize global
        int userId = Util.getUserId(Process.myUid());
        PrivacyManager.setSettingList(getRandomizeWork(context, userId));

        // Randomize applications
        for (int i = 1; i <= listApp.size(); i++) {
            int uid = listApp.get(i - 1).uid;
            List<PSetting> listSetting = getRandomizeWork(context, uid);
            PrivacyManager.setSettingList(listSetting);

            if (first == 0)
                if (listSetting.size() > 0)
                    first = i;
            if (first > 0 && first < listApp.size())
                notifyProgress(context, Util.NOTIFY_RANDOMIZE, format,
                        100 * (i - first) / (listApp.size() - first));
        }
        if (first == 0)
            Util.log(null, Log.WARN, "Nothing to randomize");
    }

    private static List<PSetting> getRandomizeWork(Context context, int uid) {
        List<PSetting> listWork = new ArrayList<PSetting>();

        if (PrivacyManager.getSettingBool(-uid, PrivacyManager.cSettingRandom, false)) {
            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingLatitude))
                listWork.add(new PSetting(uid, "", PrivacyManager.cSettingLatitude,
                        PrivacyManager.getRandomProp("LAT")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingLongitude))
                listWork.add(new PSetting(uid, "", PrivacyManager.cSettingLongitude,
                        PrivacyManager.getRandomProp("LON")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingAltitude))
                listWork.add(new PSetting(uid, "", PrivacyManager.cSettingAltitude,
                        PrivacyManager.getRandomProp("ALT")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingSerial))
                listWork.add(new PSetting(uid, "", PrivacyManager.cSettingSerial,
                        PrivacyManager.getRandomProp("SERIAL")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingMac))
                listWork.add(
                        new PSetting(uid, "", PrivacyManager.cSettingMac, PrivacyManager.getRandomProp("MAC")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingPhone))
                listWork.add(
                        new PSetting(uid, "", PrivacyManager.cSettingPhone, PrivacyManager.getRandomProp("PHONE")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingImei))
                listWork.add(
                        new PSetting(uid, "", PrivacyManager.cSettingImei, PrivacyManager.getRandomProp("IMEI")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingId))
                listWork.add(new PSetting(uid, "", PrivacyManager.cSettingId,
                        PrivacyManager.getRandomProp("ANDROID_ID")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingGsfId))
                listWork.add(new PSetting(uid, "", PrivacyManager.cSettingGsfId,
                        PrivacyManager.getRandomProp("GSF_ID")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingAdId))
                listWork.add(new PSetting(uid, "", PrivacyManager.cSettingAdId,
                        PrivacyManager.getRandomProp("AdvertisingId")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingCountry))
                listWork.add(new PSetting(uid, "", PrivacyManager.cSettingCountry,
                        PrivacyManager.getRandomProp("ISO3166")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingSubscriber))
                listWork.add(new PSetting(uid, "", PrivacyManager.cSettingSubscriber,
                        PrivacyManager.getRandomProp("SubscriberId")));

            if (!hasRandomOnAccess(uid, PrivacyManager.cSettingSSID))
                listWork.add(
                        new PSetting(uid, "", PrivacyManager.cSettingSSID, PrivacyManager.getRandomProp("SSID")));
        }

        return listWork;
    }

    private static boolean hasRandomOnAccess(int uid, String setting) {
        return PrivacyManager.cValueRandom.equals(PrivacyManager.getSetting(uid, setting, null));
    }

    private static List<PRestriction> getUpgradeWork(Version sVersion, int uid, boolean dangerous) {
        List<PRestriction> listWork = new ArrayList<PRestriction>();

        for (String restrictionName : PrivacyManager.getRestrictions()) {
            boolean restricted = PrivacyManager.getRestrictionEx(uid, restrictionName, null).restricted;

            for (Hook hook : PrivacyManager.getHooks(restrictionName, null)) {
                // Disable new dangerous restrictions
                if (hook.getFrom() != null) {
                    if (sVersion.compareTo(hook.getFrom()) < 0) {
                        if (hook.isDangerous()) {
                            Util.log(null, Log.WARN,
                                    "Upgrading dangerous " + hook + " from=" + hook.getFrom() + " uid=" + uid);
                            PRestriction restriction = new PRestriction(uid, hook.getRestrictionName(),
                                    hook.getName(), false, true);
                            listWork.add(restriction);
                        }

                        // Restrict replaced methods
                        if (hook.getReplacedMethod() != null) {
                            PRestriction restriction = PrivacyManager.getRestrictionEx(uid,
                                    hook.getReplacedRestriction(), hook.getReplacedMethod());
                            listWork.add(new PRestriction(uid, hook.getRestrictionName(), hook.getName(),
                                    restriction.restricted, restriction.asked));
                            Util.log(null, Log.WARN,
                                    "Replacing " + hook.getReplacedRestriction() + "/" + hook.getReplacedMethod()
                                            + " by " + hook + " from=" + hook.getFrom() + " uid=" + uid);
                        }
                    }
                }

                // Restrict dangerous
                if (dangerous && restricted && hook.isDangerous()) {
                    PRestriction restriction = new PRestriction(uid, hook.getRestrictionName(), hook.getName(),
                            true, hook.whitelist() == null);
                    if (PrivacyManager.isRestrictionSet(restriction))
                        Util.log(null, Log.WARN, "Restrict dangerous set restriction=" + restriction);
                    else {
                        Util.log(null, Log.WARN, "Restrict dangerous setting restriction=" + restriction);
                        listWork.add(restriction);
                    }
                }
            }
        }

        return listWork;
    }

    private static void notifyProgress(Context context, int id, String format, int percentage) {
        String message = String.format(format, String.format("%d %%", percentage));
        Util.log(null, Log.WARN, message);

        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        builder.setSmallIcon(R.drawable.ic_launcher);
        builder.setContentTitle(context.getString(R.string.app_name));
        builder.setContentText(message);
        builder.setWhen(System.currentTimeMillis());
        builder.setAutoCancel(percentage == 100);
        builder.setOngoing(percentage < 100);
        Notification notification = builder.build();
        notificationManager.notify(id, notification);
    }
}