Java tutorial
package me.piebridge.prevent.framework; import android.accounts.Account; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.os.SystemProperties; import android.telephony.TelephonyManager; import android.widget.Toast; import org.json.JSONObject; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.Future; import java.util.concurrent.ScheduledThreadPoolExecutor; import me.piebridge.forcestopgb.BuildConfig; import me.piebridge.forcestopgb.R; import me.piebridge.prevent.common.Configuration; import me.piebridge.prevent.common.GmsUtils; import me.piebridge.prevent.common.PackageUtils; import me.piebridge.prevent.common.PreventIntent; import me.piebridge.prevent.framework.util.HookUtils; import me.piebridge.prevent.framework.util.LogUtils; import me.piebridge.prevent.framework.util.LogcatUtils; import me.piebridge.prevent.framework.util.PreventListUtils; import me.piebridge.prevent.framework.util.SafeActionUtils; /** * Created by thom on 15/7/25. */ public class SystemReceiver extends ActivityReceiver { private Future<?> logFuture; private ScheduledThreadPoolExecutor logExecutor = new ScheduledThreadPoolExecutor(0x2); private boolean autoPrevent = true; public static final Collection<String> MANAGER_ACTIONS = Arrays.asList(PreventIntent.ACTION_GET_PACKAGES, PreventIntent.ACTION_GET_PROCESSES, PreventIntent.ACTION_GET_INFO, PreventIntent.ACTION_UPDATE_PREVENT, PreventIntent.ACTION_SYSTEM_LOG, PreventIntent.ACTION_UPDATE_CONFIGURATION, PreventIntent.ACTION_CHECK_LICENSE, PreventIntent.ACTION_SOFT_REBOOT, PreventIntent.ACTION_REBOOT); public static final Collection<String> PACKAGE_ACTIONS = Arrays.asList(Intent.ACTION_PACKAGE_RESTARTED, Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_REMOVED); public static final Collection<String> NON_SCHEME_ACTIONS = Arrays.asList(Intent.ACTION_BOOT_COMPLETED, Intent.ACTION_SCREEN_OFF, Intent.ACTION_SCREEN_ON); public SystemReceiver(Context context, Map<String, Boolean> preventPackages) { super(context, preventPackages); if (PreventListUtils.getInstance().canLoadConfiguration(mContext)) { Configuration configuration = PreventListUtils.getInstance().loadConfiguration(mContext); setForceStopTimeout(configuration.getForceStopTimeout()); SystemHook.setDestroyProcesses(configuration.isDestroyProcesses()); SystemHook.setLockSyncSettings(configuration.isLockSyncSettings()); setAutoPrevent(configuration.isAutoPrevent()); SystemHook.setStopSignatureApps(configuration.isStopSignatureApps()); SystemHook.setUseAppStandby(configuration.isUseAppStandby()); } } @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (MANAGER_ACTIONS.contains(action)) { handleManager(context, intent, action); } else if (PACKAGE_ACTIONS.contains(action)) { handlePackage(intent, action); } else if (NON_SCHEME_ACTIONS.contains(action)) { handleNonScheme(action); } } private void handleManager(Context context, Intent intent, String action) { if (PreventIntent.ACTION_GET_PACKAGES.equals(action)) { handleGetPackages(action); } else if (PreventIntent.ACTION_GET_PROCESSES.equals(action)) { handleGetProcesses(context, action); } else if (PreventIntent.ACTION_GET_INFO.equals(action)) { handleGetInfo(); } else if (PreventIntent.ACTION_UPDATE_PREVENT.equals(action)) { handleUpdatePrevent(action, intent); } else if (PreventIntent.ACTION_SYSTEM_LOG.equals(action)) { sendLogAsync(); } else if (PreventIntent.ACTION_UPDATE_CONFIGURATION.equals(action)) { handleConfiguration(intent.getBundleExtra(PreventIntent.EXTRA_CONFIGURATION)); } else if (PreventIntent.ACTION_CHECK_LICENSE.equals(action)) { handleCheckLicense(context, intent); } else if (PreventIntent.ACTION_SOFT_REBOOT.equals(action)) { softReboot(); } else if (PreventIntent.ACTION_REBOOT.equals(action)) { reboot(); } } private void reboot() { SystemProperties.set("sys.powerctl", "reboot"); } private void softReboot() { SystemProperties.set("ctl.restart", "surfaceflinger"); SystemProperties.set("ctl.restart", "zygote"); } private void handleGetInfo() { Map<String, Object> info = new LinkedHashMap<String, Object>(); info.put("method", SystemHook.getMethod()); info.put("version", SystemHook.getVersion()); info.put("name", BuildConfig.VERSION_NAME); info.put("code", BuildConfig.VERSION_CODE); if (PreventListUtils.getInstance().canLoadConfiguration(mContext)) { Configuration configuration = PreventListUtils.getInstance().loadConfiguration(mContext); info.putAll(configuration.getMap()); } setResultData(new JSONObject(info).toString()); } private void handleConfiguration(Bundle bundle) { setForceStopTimeout(bundle.getLong(PreventIntent.KEY_FORCE_STOP_TIMEOUT)); SystemHook.setDestroyProcesses(bundle.getBoolean(PreventIntent.KEY_DESTROY_PROCESSES)); SystemHook.setLockSyncSettings(bundle.getBoolean(PreventIntent.KEY_LOCK_SYNC_SETTINGS)); SystemHook.setUseAppStandby(bundle.getBoolean(PreventIntent.KEY_USE_APP_STANDBY)); setAutoPrevent(bundle.getBoolean(PreventIntent.KEY_AUTO_PREVENT, true)); if (bundle.containsKey(PreventIntent.KEY_STOP_SIGNATURE_APPS)) { // this is not an option can set from ui SystemHook.setStopSignatureApps(bundle.getBoolean(PreventIntent.KEY_STOP_SIGNATURE_APPS, true)); } if (bundle.containsKey(PreventIntent.KEY_PREVENT_LIST)) { updatePreventList(bundle.getStringArrayList(PreventIntent.KEY_PREVENT_LIST)); } saveConfiguration(new Configuration(bundle), true); } private void saveConfiguration(Configuration configuration, boolean force) { PreventListUtils.getInstance().save(mContext, configuration, force); } private void updatePreventList(Collection<String> preventList) { if (preventList == null) { return; } PreventLog.i("update prevent: " + preventList.size()); for (String prevent : preventList) { if (!mPreventPackages.containsKey(prevent)) { mPreventPackages.put(prevent, true); } } PreventListUtils.getInstance().save(mContext, mPreventPackages.keySet(), true); } private boolean handleCheckLicense(Context context, Intent intent) { String user = intent.getStringExtra(Intent.EXTRA_USER); Map<String, Set<String>> users = new LinkedHashMap<String, Set<String>>(); for (Account account : ActivityManagerServiceHook.getAccountWatcher().getEnabledAccounts()) { Set<String> accounts = users.get(account.type); if (accounts == null) { accounts = new LinkedHashSet<String>(); users.put(account.type, accounts); } accounts.add(account.name); if (PackageUtils.equals(account.name, user)) { setResultCode(0x1); return true; } } String number = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number(); if (number != null) { number = number.replace("-", ""); number = number.replace(" ", ""); Set<String> numbers = users.get(""); if (numbers == null) { numbers = new LinkedHashSet<String>(); users.put("", numbers); } numbers.add(number); if (PackageUtils.equals(number, user)) { setResultCode(0x1); return true; } } setResultCode(0x0); setResultData(users.toString()); return false; } private void handlePackage(Intent intent, String action) { String packageName = PackageUtils.getPackageName(intent); if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) { handlePackageRestarted("PACKAGE_RESTARTED", packageName); } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { onPackageAdded(intent); } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { onPackageRemoved(intent); } } protected void onPackageAdded(Intent intent) { String packageName = PackageUtils.getPackageName(intent); SafeActionUtils.onPackageChanged(packageName); if (BuildConfig.APPLICATION_ID.equals(packageName) && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { SystemHook.setSupported(true); PreventListUtils.getInstance().save(mContext, mPreventPackages.keySet(), false); Configuration configuration = new Configuration(new Bundle()); configuration.setForceStopTimeout(forceStopTimeout); configuration.setDestroyProcesses(SystemHook.isDestroyProcesses()); configuration.setLockSyncSettings(SystemHook.isLockSyncSettings()); configuration.setAutoPrevent(autoPrevent); configuration.setStopSignatureApps(SystemHook.isStopSignatureApps()); configuration.setUseAppStandby(SystemHook.isUseAppStandby()); PreventListUtils.getInstance().save(mContext, configuration, false); } else if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) && autoPrevent) { mPreventPackages.put(packageName, true); showUpdated(packageName, mPreventPackages.size()); PreventListUtils.getInstance().save(mContext, mPreventPackages.keySet(), true); } } private String getLabel(PackageManager pm, String packageName) { try { return pm.getApplicationInfo(packageName, 0).loadLabel(pm).toString(); } catch (PackageManager.NameNotFoundException e) { PreventLog.d("cannot find application " + packageName, e); return packageName; } } private void showUpdated(String packageName, int size) { try { PackageManager pm = mContext.getPackageManager(); Resources resources = pm.getResourcesForApplication(BuildConfig.APPLICATION_ID); String message = resources.getString(R.string.updated_prevents, size) + "(" + getLabel(pm, packageName) + ")"; Toast.makeText(mContext, message, Toast.LENGTH_LONG).show(); } catch (PackageManager.NameNotFoundException e) { PreventLog.d("cannot find application " + BuildConfig.APPLICATION_ID, e); } catch (RuntimeException e) { PreventLog.d("cannot show toast", e); } } protected void onPackageRemoved(Intent intent) { String packageName = PackageUtils.getPackageName(intent); SafeActionUtils.onPackageChanged(packageName); onPackageRemoved(packageName); if (BuildConfig.APPLICATION_ID.equals(packageName) && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { SystemHook.setSupported(false); PreventListUtils.getInstance().onRemoved(mContext); } else if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { mPreventPackages.remove(packageName); PreventListUtils.getInstance().save(mContext, mPreventPackages.keySet(), true); } } private void handleNonScheme(String action) { if (Intent.ACTION_SCREEN_OFF.equals(action)) { onScreenOff(); } else if (Intent.ACTION_SCREEN_ON.equals(action)) { onScreenOn(); } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { if (!SystemHook.isSupported()) { PreventListUtils.notifyNotSupported(mContext); } else if (!PreventListUtils.getInstance().canLoad(mContext)) { PreventListUtils.notifyNoPrevents(mContext); } } } private void handleGetProcesses(Context context, String action) { Map<String, Set<Long>> running = getRunningAppProcesses(context); Map<String, Long> leaving = getLeavingPackages(); for (Map.Entry<String, Long> entry : leaving.entrySet()) { String packageName = entry.getKey(); Set<Long> status = running.get(packageName); if (status != null) { long elapsed = entry.getValue(); if (elapsed % 0xa == 0) { elapsed += 1; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && hasHighPriority(packageName)) { status.add(-elapsed); } else { status.add(elapsed); } } } LogUtils.logRequestInfo(action, null, running.size()); setResultData(toJSON(running)); abortBroadcast(); } private void handleGetPackages(String action) { Map<String, Boolean> preventPackages = new TreeMap<String, Boolean>(mPreventPackages); if (!GmsUtils.canStopGms()) { for (String packageName : GmsUtils.getGmsPackages()) { if (Boolean.TRUE.equals(preventPackages.get(packageName))) { preventPackages.put(packageName, false); } } } int size = preventPackages.size(); setResultCode(size); setResultData(new JSONObject(preventPackages).toString()); LogUtils.logRequestInfo(action, null, size); abortBroadcast(); } private void handleUpdatePrevent(String action, Intent intent) { String[] packages = intent.getStringArrayExtra(PreventIntent.EXTRA_PACKAGES); boolean prevent = intent.getBooleanExtra(PreventIntent.EXTRA_PREVENT, true); Map<String, Boolean> prevents = mPreventPackages; for (String name : packages) { if (prevent) { int count = countCounter(name); prevents.put(name, count == 0); } else { prevents.remove(name); } } PreventListUtils.getInstance().save(mContext, mPreventPackages.keySet(), true); setResultCode(prevents.size()); setResultData(new JSONObject(prevents).toString()); LogUtils.logRequestInfo(action, null, prevents.size()); abortBroadcast(); } private String toJSON(Map<String, Set<Long>> processes) { Map<String, String> results = new HashMap<String, String>(); for (Map.Entry<String, Set<Long>> entry : processes.entrySet()) { results.put(entry.getKey(), convertSet(entry.getValue())); } return new JSONObject(results).toString(); } private String convertSet(Set<Long> value) { StringBuilder sb = new StringBuilder(); Iterator<Long> it = value.iterator(); while (it.hasNext()) { Long v = it.next(); if (v != null) { sb.append(v); if (it.hasNext()) { sb.append(","); } } } return sb.toString(); } private Map<String, Set<Long>> getRunningAppProcesses(Context context) { Map<String, Set<Long>> running = new HashMap<String, Set<Long>>(); Set<String> services = getRunningServices(context); ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> processes = activityManager.getRunningAppProcesses(); if (processes == null) { PreventLog.w("cannot get running processes"); return running; } for (ActivityManager.RunningAppProcessInfo process : processes) { for (String pkg : process.pkgList) { Set<Long> importance = running.get(pkg); if (importance == null) { importance = new LinkedHashSet<Long>(); running.put(pkg, importance); } if (process.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE) { importance.add((long) process.importance); } else if (services.contains(pkg)) { importance.add((long) process.importance); } else { importance.add((long) -process.importance); } } } return running; } private Set<String> getRunningServices(Context context) { Set<String> services = new HashSet<String>(); for (ActivityManager.RunningServiceInfo service : HookUtils.getServices(context)) { if (service.started) { services.add(service.service.getPackageName()); } } return services; } private void handlePackageRestarted(String action, String packageName) { LogUtils.logRequestInfo(action, packageName, -1); removePackageCounters(packageName); SystemHook.updateRunningGapps(packageName, false); if (mPreventPackages.containsKey(packageName)) { mPreventPackages.put(packageName, true); } SystemHook.killNoFather(); } private void sendLogAsync() { if (logFuture != null) { logFuture.cancel(true); } logFuture = logExecutor.submit(new Runnable() { @Override public void run() { LogcatUtils.logcat(LogcatUtils.PREVENT, "-s Prevent:v PreventUI:v"); LogcatUtils.logcat(LogcatUtils.SYSTEM, "ContentResolver:s *:v"); LogcatUtils.logcat(mContext, LogcatUtils.BOOT); LogcatUtils.logcat(mContext, LogcatUtils.PREVENT); LogcatUtils.logcat(mContext, LogcatUtils.SYSTEM); LogcatUtils.completed(mContext); } }); } public void setAutoPrevent(boolean autoPrevent) { PreventLog.i("update auto prevent to " + autoPrevent); this.autoPrevent = autoPrevent; } }