mobile/android/base/health/SessionInformation.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/health/SessionInformation.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,137 @@
     1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +package org.mozilla.gecko.health;
    1.10 +
    1.11 +import android.content.SharedPreferences;
    1.12 +import android.util.Log;
    1.13 +
    1.14 +import org.mozilla.gecko.GeckoApp;
    1.15 +
    1.16 +import org.json.JSONException;
    1.17 +import org.json.JSONObject;
    1.18 +
    1.19 +public class SessionInformation {
    1.20 +    private static final String LOG_TAG = "GeckoSessInfo";
    1.21 +
    1.22 +    public static final String PREFS_SESSION_START = "sessionStart";
    1.23 +
    1.24 +    public final long wallStartTime;    // System wall clock.
    1.25 +    public final long realStartTime;    // Realtime clock.
    1.26 +
    1.27 +    private final boolean wasOOM;
    1.28 +    private final boolean wasStopped;
    1.29 +
    1.30 +    private volatile long timedGeckoStartup = -1;
    1.31 +    private volatile long timedJavaStartup = -1;
    1.32 +
    1.33 +    // Current sessions don't (right now) care about wasOOM/wasStopped.
    1.34 +    // Eventually we might want to lift that logic out of GeckoApp.
    1.35 +    public SessionInformation(long wallTime, long realTime) {
    1.36 +        this(wallTime, realTime, false, false);
    1.37 +    }
    1.38 +
    1.39 +    // Previous sessions do...
    1.40 +    public SessionInformation(long wallTime, long realTime, boolean wasOOM, boolean wasStopped) {
    1.41 +        this.wallStartTime = wallTime;
    1.42 +        this.realStartTime = realTime;
    1.43 +        this.wasOOM = wasOOM;
    1.44 +        this.wasStopped = wasStopped;
    1.45 +    }
    1.46 +
    1.47 +    /**
    1.48 +     * Initialize a new SessionInformation instance from the supplied prefs object.
    1.49 +     *
    1.50 +     * This includes retrieving OOM/crash data, as well as timings.
    1.51 +     *
    1.52 +     * If no wallStartTime was found, that implies that the previous
    1.53 +     * session was correctly recorded, and an object with a zero
    1.54 +     * wallStartTime is returned.
    1.55 +     */
    1.56 +    public static SessionInformation fromSharedPrefs(SharedPreferences prefs) {
    1.57 +        boolean wasOOM = prefs.getBoolean(GeckoApp.PREFS_OOM_EXCEPTION, false);
    1.58 +        boolean wasStopped = prefs.getBoolean(GeckoApp.PREFS_WAS_STOPPED, true);
    1.59 +        long wallStartTime = prefs.getLong(PREFS_SESSION_START, 0L);
    1.60 +        long realStartTime = 0L;
    1.61 +        Log.d(LOG_TAG, "Building SessionInformation from prefs: " +
    1.62 +                       wallStartTime + ", " + realStartTime + ", " +
    1.63 +                       wasStopped + ", " + wasOOM);
    1.64 +        return new SessionInformation(wallStartTime, realStartTime, wasOOM, wasStopped);
    1.65 +    }
    1.66 +
    1.67 +    /**
    1.68 +     * Initialize a new SessionInformation instance to 'split' the current
    1.69 +     * session.
    1.70 +     */
    1.71 +    public static SessionInformation forRuntimeTransition() {
    1.72 +        final boolean wasOOM = false;
    1.73 +        final boolean wasStopped = true;
    1.74 +        final long wallStartTime = System.currentTimeMillis();
    1.75 +        final long realStartTime = android.os.SystemClock.elapsedRealtime();
    1.76 +        Log.v(LOG_TAG, "Recording runtime session transition: " +
    1.77 +                       wallStartTime + ", " + realStartTime);
    1.78 +        return new SessionInformation(wallStartTime, realStartTime, wasOOM, wasStopped);
    1.79 +    }
    1.80 +
    1.81 +    public boolean wasKilled() {
    1.82 +        return wasOOM || !wasStopped;
    1.83 +    }
    1.84 +
    1.85 +    /**
    1.86 +     * Record the beginning of this session to SharedPreferences by
    1.87 +     * recording our start time. If a session was already recorded, it is
    1.88 +     * overwritten (there can only be one running session at a time). Does
    1.89 +     * not commit the editor.
    1.90 +     */
    1.91 +    public void recordBegin(SharedPreferences.Editor editor) {
    1.92 +        Log.d(LOG_TAG, "Recording start of session: " + this.wallStartTime);
    1.93 +        editor.putLong(PREFS_SESSION_START, this.wallStartTime);
    1.94 +    }
    1.95 +
    1.96 +    /**
    1.97 +     * Record the completion of this session to SharedPreferences by
    1.98 +     * deleting our start time. Does not commit the editor.
    1.99 +     */
   1.100 +    public void recordCompletion(SharedPreferences.Editor editor) {
   1.101 +        Log.d(LOG_TAG, "Recording session done: " + this.wallStartTime);
   1.102 +        editor.remove(PREFS_SESSION_START);
   1.103 +    }
   1.104 +
   1.105 +    /**
   1.106 +     * Return the JSON that we'll put in the DB for this session.
   1.107 +     */
   1.108 +    public JSONObject getCompletionJSON(String reason, long realEndTime) throws JSONException {
   1.109 +        long durationSecs = (realEndTime - this.realStartTime) / 1000;
   1.110 +        JSONObject out = new JSONObject();
   1.111 +        out.put("r", reason);
   1.112 +        out.put("d", durationSecs);
   1.113 +        if (this.timedGeckoStartup > 0) {
   1.114 +            out.put("sg", this.timedGeckoStartup);
   1.115 +        }
   1.116 +        if (this.timedJavaStartup > 0) {
   1.117 +            out.put("sj", this.timedJavaStartup);
   1.118 +        }
   1.119 +        return out;
   1.120 +    }
   1.121 +
   1.122 +    public JSONObject getCrashedJSON() throws JSONException {
   1.123 +        JSONObject out = new JSONObject();
   1.124 +        // We use ints here instead of booleans, because we're packing
   1.125 +        // stuff into JSON, and saving bytes in the DB is a worthwhile
   1.126 +        // goal.
   1.127 +        out.put("oom", this.wasOOM ? 1 : 0);
   1.128 +        out.put("stopped", this.wasStopped ? 1 : 0);
   1.129 +        out.put("r", "A");
   1.130 +        return out;
   1.131 +    }
   1.132 +
   1.133 +    public void setTimedGeckoStartup(final long duration) {
   1.134 +        timedGeckoStartup = duration;
   1.135 +    }
   1.136 +
   1.137 +    public void setTimedJavaStartup(final long duration) {
   1.138 +        timedJavaStartup = duration;
   1.139 +    }
   1.140 +}

mercurial