From b911cf5dfef59e10936a56165841ae32cf7ba574 Mon Sep 17 00:00:00 2001 From: Ryan Steckler Date: Thu, 30 Oct 2014 11:03:37 -0700 Subject: [PATCH 1/4] File versioning so we can reset stats on upgrades --- app/build.gradle | 4 ++-- app/src/main/AndroidManifest.xml | 2 ++ .../nlpunbounce/ActivityReceiver.java | 3 +++ .../nlpunbounce/HomeFragment.java | 7 ++++++ .../nlpunbounce/hooks/Wakelocks.java | 22 +++++++++++++++++- .../models/UnbounceStatsCollection.java | 23 +++++++++++++++---- app/src/main/res/xml/preferences.xml | 2 +- 7 files changed, 55 insertions(+), 8 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c980eeb..5472bb8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { applicationId 'com.ryansteckler.nlpunbounce' minSdkVersion 16 targetSdkVersion 20 - versionCode 38 - versionName '2.0.2' + versionCode 39 + versionName '2.0.3' } buildTypes { release { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 77bb95a..61de21a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -34,7 +34,9 @@ + + diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/ActivityReceiver.java b/app/src/main/java/com/ryansteckler/nlpunbounce/ActivityReceiver.java index fd8d4c0..154a4dc 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/ActivityReceiver.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/ActivityReceiver.java @@ -25,6 +25,7 @@ public class ActivityReceiver extends BroadcastReceiver { public static final String STATS_REFRESHED_ACTION = "com.ryansteckler.nlpunbounce.STATS_REFRESHED_ACTION"; public static final String CREATE_FILES_ACTION = "com.ryansteckler.nlpunbounce.CREATE_FILES_ACTION"; + public static final String RESET_FILES_ACTION = "com.ryansteckler.nlpunbounce.RESET_FILES_ACTION"; public static final String PUSH_NETWORK_STATS = "com.ryansteckler.nlpunbounce.PUSH_NETWORK_STATS"; public ActivityReceiver() { @@ -35,6 +36,8 @@ public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(CREATE_FILES_ACTION)) { UnbounceStatsCollection.getInstance().createFiles(context); + } else if (action.equals(RESET_FILES_ACTION)) { + UnbounceStatsCollection.getInstance().recreateFiles(context); } else if (action.equals(PUSH_NETWORK_STATS)) { UnbounceStatsCollection.getInstance().pushStatsToNetworkInternal(context); } diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java b/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java index 23803c1..66ff636 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java @@ -46,6 +46,7 @@ import com.ryansteckler.nlpunbounce.helpers.RootHelper; import com.ryansteckler.nlpunbounce.helpers.SettingsHelper; import com.ryansteckler.nlpunbounce.helpers.ThemeHelper; +import com.ryansteckler.nlpunbounce.hooks.Wakelocks; import com.ryansteckler.nlpunbounce.models.UnbounceStatsCollection; @@ -88,6 +89,12 @@ public void onCreate(Bundle savedInstanceState) { ThemeHelper.onActivityCreateSetTheme(this.getActivity()); setHasOptionsMenu(true); + SharedPreferences prefs = getActivity().getSharedPreferences("com.ryansteckler.nlpunbounce" + "_preferences", Context.MODE_WORLD_READABLE); + String lastVersion = prefs.getString("file_version", "0"); + if (!lastVersion.equals(Wakelocks.FILE_VERSION)) { + //Reset stats + UnbounceStatsCollection.getInstance().recreateFiles(getActivity()); + } } @Override diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java b/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java index c0975e4..2fdf10b 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java @@ -37,7 +37,8 @@ public class Wakelocks implements IXposedHookLoadPackage { private static final String TAG = "Amplify: "; - private static final String VERSION = "2.0.2"; //This needs to be pulled from the manifest or gradle build. + public static final String VERSION = "2.0.3"; //This needs to be pulled from the manifest or gradle build. + public static final String FILE_VERSION = "2"; //This needs to be pulled from the manifest or gradle build. private HashMap mLastWakelockAttempts = null; //The last time each wakelock was allowed. private HashMap mLastAlarmAttempts = null; //The last time each alarm was allowed. // private HashMap mLastServiceAttempts = null; //The last time each wakelock was allowed. @@ -73,11 +74,28 @@ public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { hookAlarms(lpparam); hookWakeLocks(lpparam); hookServices(lpparam); + resetFilesIfNeeded(null); } else if (lpparam.packageName.equals("com.ryansteckler.nlpunbounce")) { hookAmplifyClasses(lpparam); } } + private void resetFilesIfNeeded(Context context) { + //Get the version number and compare it to our app version. + String lastVersion = m_prefs.getString("file_version", "0"); + if (!lastVersion.equals(FILE_VERSION)) { + //Reset stats + defaultLog("Resetting stat files on version upgrade."); + if (context != null) { + Intent intent = new Intent(ActivityReceiver.CREATE_FILES_ACTION); + try { + context.sendBroadcast(intent); + } catch (IllegalStateException ise) { + } + } + UnbounceStatsCollection.getInstance().resetLocalStats(UnbounceStatsCollection.STAT_CURRENT); + } + } private void hookAmplifyClasses(LoadPackageParam lpparam) { findAndHookMethod("com.ryansteckler.nlpunbounce.HomeFragment", lpparam.classLoader, "isUnbounceServiceRunning", new XC_MethodHook() { @Override @@ -448,6 +466,8 @@ private void updateStatsIfNeeded(Context context) { long timeSinceLastUpdateStats = now - mLastUpdateStats; if (timeSinceLastUpdateStats > mUpdateStatsFrequency) { + resetFilesIfNeeded(context); + if (!UnbounceStatsCollection.getInstance().saveNow(context)) { //Request the activity to create the files. Intent intent = new Intent(ActivityReceiver.CREATE_FILES_ACTION); diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java b/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java index 2942b94..77fd3ca 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java @@ -16,6 +16,7 @@ import com.ryansteckler.nlpunbounce.ActivityReceiver; import com.ryansteckler.nlpunbounce.XposedReceiver; import com.ryansteckler.nlpunbounce.helpers.NetworkHelper; +import com.ryansteckler.nlpunbounce.hooks.Wakelocks; import java.io.File; import java.io.FileInputStream; @@ -80,7 +81,7 @@ public Long getRunningSince() { } public String getRunningSinceFormatted() { - long now = SystemClock.elapsedRealtime(); + long now = System.currentTimeMillis(); long running = now - mRunningSince; long years = TimeUnit.MILLISECONDS.toDays(running) / 365; @@ -577,7 +578,7 @@ public void resetStats(Context context, int statType) { if (statType == STAT_CURRENT) { mCurrentStats.clear(); - mRunningSince = SystemClock.elapsedRealtime(); + mRunningSince = System.currentTimeMillis(); clearStatFile(context, STATS_FILENAME_CURRENT); } else if (statType == STAT_PUSH) { @@ -590,7 +591,7 @@ public void resetLocalStats(int statType) { if (statType == STAT_CURRENT) { mCurrentStats.clear(); - mRunningSince = SystemClock.elapsedRealtime(); + mRunningSince = System.currentTimeMillis(); } else if (statType == STAT_PUSH) { mSincePushStats.clear(); @@ -643,6 +644,7 @@ private void clearStatFile(Context context, String filename) { } public boolean saveNow(Context context) { + if (!saveStatsToFile(STATS_FILENAME_CURRENT, mCurrentStats)) { return false; } @@ -820,6 +822,14 @@ public void refreshPrefs(XSharedPreferences prefs) { mGlobalParticipation = prefs.getBoolean("global_participation", true); } + public void recreateFiles(Context context) { + Log.d("Amplify: ", "Removing file: " + STATS_DIRECTORY + STATS_FILENAME_CURRENT); + new File(STATS_DIRECTORY + STATS_FILENAME_CURRENT).delete(); + new File(STATS_DIRECTORY + STATS_FILENAME_GLOBAL).delete(); + new File(STATS_DIRECTORY + STATS_FILENAME_PUSH).delete(); + createFiles(context); + } + public void createFiles(Context context) { try { if (!new File(STATS_DIRECTORY + STATS_FILENAME_CURRENT).exists()) { @@ -843,6 +853,11 @@ public void createFiles(Context context) { } catch (IOException e) { e.printStackTrace(); } - + Log.d("Amplify: ", "Writing creation version"); + SharedPreferences prefs = context.getSharedPreferences("com.ryansteckler.nlpunbounce" + "_preferences", Context.MODE_WORLD_READABLE); + SharedPreferences.Editor edit = prefs.edit(); + edit.putString("file_version", Wakelocks.FILE_VERSION); + edit.apply(); + mRunningSince = System.currentTimeMillis(); } } diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index a8de8db..2744312 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -62,7 +62,7 @@ android:key="about_author" android:editable="false" android:defaultValue="0" - android:summary="Version: 2.0.2" + android:summary="Version: 2.0.3" /> Date: Thu, 30 Oct 2014 11:03:54 -0700 Subject: [PATCH 2/4] Check to make sure the version of kernel and activity match --- .../nlpunbounce/HomeFragment.java | 45 +++++++++++++++---- .../nlpunbounce/hooks/Wakelocks.java | 7 +++ app/src/main/res/values/strings.xml | 4 +- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java b/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java index 66ff636..77b9640 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java @@ -65,9 +65,10 @@ public class HomeFragment extends Fragment { private int mSetupFailureStep = SETUP_FAILURE_NONE; //We're optimists :) private final static int SETUP_FAILURE_NONE = 0; //We're good. The service is running. private final static int SETUP_FAILURE_SERVICE = 1; //The service isn't running, but Xposed is installed. - private final static int SETUP_FAILURE_XPOSED_RUNNING = 2; //Xposed isn't running ("installed") - private final static int SETUP_FAILURE_XPOSED_INSTALL = 3; //Xposed isn't installed - private final static int SETUP_FAILURE_ROOT = 4; //There's no root access. + private final static int SETUP_FAILURE_VERSION = 2; //The service isn't running, but Xposed is installed. + private final static int SETUP_FAILURE_XPOSED_RUNNING = 3; //Xposed isn't running ("installed") + private final static int SETUP_FAILURE_XPOSED_INSTALL = 4; //Xposed isn't installed + private final static int SETUP_FAILURE_ROOT = 5; //There's no root access. /** @@ -145,12 +146,15 @@ private void handleSetup(final View view) { //Let's find out why the service isn't running: if (!isUnbounceServiceRunning()) { mSetupFailureStep = SETUP_FAILURE_SERVICE; - if (!isXposedRunning()) { - mSetupFailureStep = SETUP_FAILURE_XPOSED_RUNNING; - if (!isXposedInstalled()) { - mSetupFailureStep = SETUP_FAILURE_XPOSED_INSTALL; - if (!RootHelper.isDeviceRooted()) { - mSetupFailureStep = SETUP_FAILURE_ROOT; + if (!getAmplifyKernelVersion().equals(Wakelocks.VERSION)) { + mSetupFailureStep = SETUP_FAILURE_VERSION; + if (!isXposedRunning()) { + mSetupFailureStep = SETUP_FAILURE_XPOSED_RUNNING; + if (!isXposedInstalled()) { + mSetupFailureStep = SETUP_FAILURE_XPOSED_INSTALL; + if (!RootHelper.isDeviceRooted()) { + mSetupFailureStep = SETUP_FAILURE_ROOT; + } } } } @@ -278,6 +282,9 @@ public void onClick(View view) { } else if (mSetupFailureStep == SETUP_FAILURE_SERVICE) { //Service isn't running handleServiceFailure(problemText, nextButtonText, nextButton); + } else if (mSetupFailureStep == SETUP_FAILURE_VERSION) { + //Service is the wrong version + handleVersionFailure(problemText, nextButtonText, nextButton); } else if (mSetupFailureStep == SETUP_FAILURE_XPOSED_RUNNING) { //Xposed isn't running handleXposedRunningFailure(problemText, nextButtonText, nextButton); @@ -399,6 +406,19 @@ public void onClick(View view) { }); } + private void handleVersionFailure(TextView problemText, TextView nextButtonText, LinearLayout nextButton) { + nextButtonText.setText(getActivity().getResources().getString(R.string.welcome_banner_button_fixit)); + String errorText = getResources().getString(R.string.welcome_banner_problem_version); + problemText.setText(Html.fromHtml(errorText)); + problemText.setMovementMethod(LinkMovementMethod.getInstance()); + nextButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + getActivity().finish(); + } + }); + } + private void handleServiceFailure(TextView problemText, TextView nextButtonText, LinearLayout nextButton) { nextButtonText.setText(getActivity().getResources().getString(R.string.welcome_banner_button_fixit)); String errorText = getResources().getString(R.string.welcome_banner_problem_service); @@ -865,6 +885,13 @@ public boolean isUnbounceServiceRunning() { return false; } + public String getAmplifyKernelVersion() { + //The Unbounce hook changes this to true. + return "0"; + } + + + public boolean isXposedRunning() { return new File("/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar").exists(); } diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java b/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java index 2fdf10b..55e3f2e 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/hooks/Wakelocks.java @@ -103,6 +103,13 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { param.setResult(true); } }); + findAndHookMethod("com.ryansteckler.nlpunbounce.HomeFragment", lpparam.classLoader, "getAmplifyKernelVersion", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + param.setResult(VERSION); + } + }); + } private void setupReceiver(XC_MethodHook.MethodHookParam param) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2a87c78..6c08127 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -161,9 +161,9 @@ May you have a long [battery] life! "Something went wrong. Let's find out what and get it fixed..." "We've setup some battery saving defaults for you. Enjoy your new battery life!" "It looks like you haven't enabled the Amplify module. Click \"FIX IT\", make sure Amplify is checked, then reboot." +"It looks like you just upgraded Amplify but haven't rebooted yet. Click \"FIX IT\", then reboot." "Xposed isn't running. Click \"FIX IT\", then click \"Install/Update\" and reboot your device." -"Xposed isn't installed. Xposed is required for Amplify and many other root applications. Once the download is finished, click INSTALL, then launch Amplify again. -If you'd like to learn more about Xposed, visit %1$s." +"Xposed isn't installed. Xposed is required for Amplify and many other root applications. Once the download is finished, click INSTALL, then launch Amplify again. If you'd like to learn more about Xposed, visit %1$s." "It looks like your device isn't rooted. Amplify requires a rooted device to function properly. If you're interested in rooting your device, please visit %1$s." "NEXT" "FIX IT" From 34a96d0996e1c330ae0127ed5294024ada3e6ded Mon Sep 17 00:00:00 2001 From: Ryan Steckler Date: Thu, 30 Oct 2014 13:22:31 -0700 Subject: [PATCH 3/4] Reset runningSince --- .../ryansteckler/nlpunbounce/HomeFragment.java | 18 +++++++++++++----- .../models/UnbounceStatsCollection.java | 2 ++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java b/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java index 77b9640..b39fa05 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/HomeFragment.java @@ -95,6 +95,14 @@ public void onCreate(Bundle savedInstanceState) { if (!lastVersion.equals(Wakelocks.FILE_VERSION)) { //Reset stats UnbounceStatsCollection.getInstance().recreateFiles(getActivity()); + Intent intent = new Intent(XposedReceiver.RESET_ACTION); + intent.putExtra(XposedReceiver.STAT_TYPE, UnbounceStatsCollection.STAT_CURRENT); + try { + getActivity().sendBroadcast(intent); + } catch (IllegalStateException ise) { + + } + } } @@ -137,17 +145,17 @@ private void handleSetup(final View view) { final SharedPreferences prefs = getActivity().getSharedPreferences("com.ryansteckler.nlpunbounce" + "_preferences", Context.MODE_WORLD_READABLE); boolean firstRun = prefs.getBoolean("first_launch", true); - if (!isUnbounceServiceRunning() || firstRun) { + if (!getAmplifyKernelVersion().equals(Wakelocks.VERSION) || firstRun) { //Show the banner final LinearLayout banner = (LinearLayout)view.findViewById(R.id.banner); banner.setVisibility(View.VISIBLE); //Let's find out why the service isn't running: - if (!isUnbounceServiceRunning()) { - mSetupFailureStep = SETUP_FAILURE_SERVICE; - if (!getAmplifyKernelVersion().equals(Wakelocks.VERSION)) { - mSetupFailureStep = SETUP_FAILURE_VERSION; + if (!getAmplifyKernelVersion().equals(Wakelocks.VERSION)) { + mSetupFailureStep = SETUP_FAILURE_VERSION; + if (!isUnbounceServiceRunning()) { + mSetupFailureStep = SETUP_FAILURE_SERVICE; if (!isXposedRunning()) { mSetupFailureStep = SETUP_FAILURE_XPOSED_RUNNING; if (!isXposedInstalled()) { diff --git a/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java b/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java index 77fd3ca..369f585 100644 --- a/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java +++ b/app/src/main/java/com/ryansteckler/nlpunbounce/models/UnbounceStatsCollection.java @@ -74,6 +74,7 @@ public static UnbounceStatsCollection getInstance() } private UnbounceStatsCollection() { + mRunningSince = System.currentTimeMillis(); } public Long getRunningSince() { @@ -590,6 +591,7 @@ else if (statType == STAT_PUSH) { public void resetLocalStats(int statType) { if (statType == STAT_CURRENT) { + mCurrentStats.clear(); mRunningSince = System.currentTimeMillis(); } From fc6734e287256523a4d0445659c49ccf96d23afe Mon Sep 17 00:00:00 2001 From: Ryan Steckler Date: Thu, 30 Oct 2014 13:59:57 -0700 Subject: [PATCH 4/4] Bumped to version 2.0.3 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 5472bb8..b6e7b8f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { applicationId 'com.ryansteckler.nlpunbounce' minSdkVersion 16 targetSdkVersion 20 - versionCode 39 + versionCode 40 versionName '2.0.3' } buildTypes {