Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- |
michael@0 | 2 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | package org.mozilla.gecko.health; |
michael@0 | 7 | |
michael@0 | 8 | import android.content.SharedPreferences; |
michael@0 | 9 | import android.util.Log; |
michael@0 | 10 | |
michael@0 | 11 | import org.mozilla.gecko.GeckoApp; |
michael@0 | 12 | |
michael@0 | 13 | import org.json.JSONException; |
michael@0 | 14 | import org.json.JSONObject; |
michael@0 | 15 | |
michael@0 | 16 | public class SessionInformation { |
michael@0 | 17 | private static final String LOG_TAG = "GeckoSessInfo"; |
michael@0 | 18 | |
michael@0 | 19 | public static final String PREFS_SESSION_START = "sessionStart"; |
michael@0 | 20 | |
michael@0 | 21 | public final long wallStartTime; // System wall clock. |
michael@0 | 22 | public final long realStartTime; // Realtime clock. |
michael@0 | 23 | |
michael@0 | 24 | private final boolean wasOOM; |
michael@0 | 25 | private final boolean wasStopped; |
michael@0 | 26 | |
michael@0 | 27 | private volatile long timedGeckoStartup = -1; |
michael@0 | 28 | private volatile long timedJavaStartup = -1; |
michael@0 | 29 | |
michael@0 | 30 | // Current sessions don't (right now) care about wasOOM/wasStopped. |
michael@0 | 31 | // Eventually we might want to lift that logic out of GeckoApp. |
michael@0 | 32 | public SessionInformation(long wallTime, long realTime) { |
michael@0 | 33 | this(wallTime, realTime, false, false); |
michael@0 | 34 | } |
michael@0 | 35 | |
michael@0 | 36 | // Previous sessions do... |
michael@0 | 37 | public SessionInformation(long wallTime, long realTime, boolean wasOOM, boolean wasStopped) { |
michael@0 | 38 | this.wallStartTime = wallTime; |
michael@0 | 39 | this.realStartTime = realTime; |
michael@0 | 40 | this.wasOOM = wasOOM; |
michael@0 | 41 | this.wasStopped = wasStopped; |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | /** |
michael@0 | 45 | * Initialize a new SessionInformation instance from the supplied prefs object. |
michael@0 | 46 | * |
michael@0 | 47 | * This includes retrieving OOM/crash data, as well as timings. |
michael@0 | 48 | * |
michael@0 | 49 | * If no wallStartTime was found, that implies that the previous |
michael@0 | 50 | * session was correctly recorded, and an object with a zero |
michael@0 | 51 | * wallStartTime is returned. |
michael@0 | 52 | */ |
michael@0 | 53 | public static SessionInformation fromSharedPrefs(SharedPreferences prefs) { |
michael@0 | 54 | boolean wasOOM = prefs.getBoolean(GeckoApp.PREFS_OOM_EXCEPTION, false); |
michael@0 | 55 | boolean wasStopped = prefs.getBoolean(GeckoApp.PREFS_WAS_STOPPED, true); |
michael@0 | 56 | long wallStartTime = prefs.getLong(PREFS_SESSION_START, 0L); |
michael@0 | 57 | long realStartTime = 0L; |
michael@0 | 58 | Log.d(LOG_TAG, "Building SessionInformation from prefs: " + |
michael@0 | 59 | wallStartTime + ", " + realStartTime + ", " + |
michael@0 | 60 | wasStopped + ", " + wasOOM); |
michael@0 | 61 | return new SessionInformation(wallStartTime, realStartTime, wasOOM, wasStopped); |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | /** |
michael@0 | 65 | * Initialize a new SessionInformation instance to 'split' the current |
michael@0 | 66 | * session. |
michael@0 | 67 | */ |
michael@0 | 68 | public static SessionInformation forRuntimeTransition() { |
michael@0 | 69 | final boolean wasOOM = false; |
michael@0 | 70 | final boolean wasStopped = true; |
michael@0 | 71 | final long wallStartTime = System.currentTimeMillis(); |
michael@0 | 72 | final long realStartTime = android.os.SystemClock.elapsedRealtime(); |
michael@0 | 73 | Log.v(LOG_TAG, "Recording runtime session transition: " + |
michael@0 | 74 | wallStartTime + ", " + realStartTime); |
michael@0 | 75 | return new SessionInformation(wallStartTime, realStartTime, wasOOM, wasStopped); |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | public boolean wasKilled() { |
michael@0 | 79 | return wasOOM || !wasStopped; |
michael@0 | 80 | } |
michael@0 | 81 | |
michael@0 | 82 | /** |
michael@0 | 83 | * Record the beginning of this session to SharedPreferences by |
michael@0 | 84 | * recording our start time. If a session was already recorded, it is |
michael@0 | 85 | * overwritten (there can only be one running session at a time). Does |
michael@0 | 86 | * not commit the editor. |
michael@0 | 87 | */ |
michael@0 | 88 | public void recordBegin(SharedPreferences.Editor editor) { |
michael@0 | 89 | Log.d(LOG_TAG, "Recording start of session: " + this.wallStartTime); |
michael@0 | 90 | editor.putLong(PREFS_SESSION_START, this.wallStartTime); |
michael@0 | 91 | } |
michael@0 | 92 | |
michael@0 | 93 | /** |
michael@0 | 94 | * Record the completion of this session to SharedPreferences by |
michael@0 | 95 | * deleting our start time. Does not commit the editor. |
michael@0 | 96 | */ |
michael@0 | 97 | public void recordCompletion(SharedPreferences.Editor editor) { |
michael@0 | 98 | Log.d(LOG_TAG, "Recording session done: " + this.wallStartTime); |
michael@0 | 99 | editor.remove(PREFS_SESSION_START); |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | /** |
michael@0 | 103 | * Return the JSON that we'll put in the DB for this session. |
michael@0 | 104 | */ |
michael@0 | 105 | public JSONObject getCompletionJSON(String reason, long realEndTime) throws JSONException { |
michael@0 | 106 | long durationSecs = (realEndTime - this.realStartTime) / 1000; |
michael@0 | 107 | JSONObject out = new JSONObject(); |
michael@0 | 108 | out.put("r", reason); |
michael@0 | 109 | out.put("d", durationSecs); |
michael@0 | 110 | if (this.timedGeckoStartup > 0) { |
michael@0 | 111 | out.put("sg", this.timedGeckoStartup); |
michael@0 | 112 | } |
michael@0 | 113 | if (this.timedJavaStartup > 0) { |
michael@0 | 114 | out.put("sj", this.timedJavaStartup); |
michael@0 | 115 | } |
michael@0 | 116 | return out; |
michael@0 | 117 | } |
michael@0 | 118 | |
michael@0 | 119 | public JSONObject getCrashedJSON() throws JSONException { |
michael@0 | 120 | JSONObject out = new JSONObject(); |
michael@0 | 121 | // We use ints here instead of booleans, because we're packing |
michael@0 | 122 | // stuff into JSON, and saving bytes in the DB is a worthwhile |
michael@0 | 123 | // goal. |
michael@0 | 124 | out.put("oom", this.wasOOM ? 1 : 0); |
michael@0 | 125 | out.put("stopped", this.wasStopped ? 1 : 0); |
michael@0 | 126 | out.put("r", "A"); |
michael@0 | 127 | return out; |
michael@0 | 128 | } |
michael@0 | 129 | |
michael@0 | 130 | public void setTimedGeckoStartup(final long duration) { |
michael@0 | 131 | timedGeckoStartup = duration; |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | public void setTimedJavaStartup(final long duration) { |
michael@0 | 135 | timedJavaStartup = duration; |
michael@0 | 136 | } |
michael@0 | 137 | } |