167063a294955285efd6b3f038aafecc92293f803Paul Rohde/*
267063a294955285efd6b3f038aafecc92293f803Paul Rohde * Copyright (C) 2015 The Android Open Source Project
367063a294955285efd6b3f038aafecc92293f803Paul Rohde *
467063a294955285efd6b3f038aafecc92293f803Paul Rohde * Licensed under the Apache License, Version 2.0 (the "License");
567063a294955285efd6b3f038aafecc92293f803Paul Rohde * you may not use this file except in compliance with the License.
667063a294955285efd6b3f038aafecc92293f803Paul Rohde * You may obtain a copy of the License at
767063a294955285efd6b3f038aafecc92293f803Paul Rohde *
867063a294955285efd6b3f038aafecc92293f803Paul Rohde *      http://www.apache.org/licenses/LICENSE-2.0
967063a294955285efd6b3f038aafecc92293f803Paul Rohde *
1067063a294955285efd6b3f038aafecc92293f803Paul Rohde * Unless required by applicable law or agreed to in writing, software
1167063a294955285efd6b3f038aafecc92293f803Paul Rohde * distributed under the License is distributed on an "AS IS" BASIS,
1267063a294955285efd6b3f038aafecc92293f803Paul Rohde * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1367063a294955285efd6b3f038aafecc92293f803Paul Rohde * See the License for the specific language governing permissions and
1467063a294955285efd6b3f038aafecc92293f803Paul Rohde * limitations under the License.
1567063a294955285efd6b3f038aafecc92293f803Paul Rohde */
1667063a294955285efd6b3f038aafecc92293f803Paul Rohde
1767063a294955285efd6b3f038aafecc92293f803Paul Rohdepackage com.android.camera.app;
1867063a294955285efd6b3f038aafecc92293f803Paul Rohde
1967063a294955285efd6b3f038aafecc92293f803Paul Rohdeimport android.content.Context;
2067063a294955285efd6b3f038aafecc92293f803Paul Rohdeimport android.content.SharedPreferences;
2167063a294955285efd6b3f038aafecc92293f803Paul Rohdeimport android.preference.PreferenceManager;
2267063a294955285efd6b3f038aafecc92293f803Paul Rohde
23d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohdeimport com.android.camera.stats.profiler.Profile;
24d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohdeimport com.android.camera.stats.profiler.Profiler;
25d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohdeimport com.android.camera.stats.profiler.Profilers;
26d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
2767063a294955285efd6b3f038aafecc92293f803Paul Rohdepublic class FirstRunDetector {
2867063a294955285efd6b3f038aafecc92293f803Paul Rohde    private static final long UNKNOWN = -1;
2967063a294955285efd6b3f038aafecc92293f803Paul Rohde    // Default SharedPreferences key for when the application was first used.
3067063a294955285efd6b3f038aafecc92293f803Paul Rohde    private static final String CLIENT_FIRST_USE_TIME = "client_first_use_time_millis";
3167063a294955285efd6b3f038aafecc92293f803Paul Rohde
3267063a294955285efd6b3f038aafecc92293f803Paul Rohde    private static class Singleton {
33d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        private static final FirstRunDetector INSTANCE = new FirstRunDetector(
34d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde              Profilers.instance().guard());
3567063a294955285efd6b3f038aafecc92293f803Paul Rohde    }
3667063a294955285efd6b3f038aafecc92293f803Paul Rohde
3767063a294955285efd6b3f038aafecc92293f803Paul Rohde    public static FirstRunDetector instance() {
3867063a294955285efd6b3f038aafecc92293f803Paul Rohde        return Singleton.INSTANCE;
3967063a294955285efd6b3f038aafecc92293f803Paul Rohde    }
4067063a294955285efd6b3f038aafecc92293f803Paul Rohde
41d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde    private final Profile mProfile;
4267063a294955285efd6b3f038aafecc92293f803Paul Rohde    private long mTimeOfFirstRun;
4367063a294955285efd6b3f038aafecc92293f803Paul Rohde    /** Flag set to true if and only if first run of application is detected. */
4467063a294955285efd6b3f038aafecc92293f803Paul Rohde    private boolean mIsFirstRun = false;
4567063a294955285efd6b3f038aafecc92293f803Paul Rohde
46d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde    private FirstRunDetector(Profiler profiler) {
47d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        mProfile = profiler.create("FirstRunDetector getTimeOfFirstRun");
48d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde    }
4967063a294955285efd6b3f038aafecc92293f803Paul Rohde
5067063a294955285efd6b3f038aafecc92293f803Paul Rohde    /**
5167063a294955285efd6b3f038aafecc92293f803Paul Rohde     * Return true if this is the first time the app was opened.
5267063a294955285efd6b3f038aafecc92293f803Paul Rohde     */
5367063a294955285efd6b3f038aafecc92293f803Paul Rohde    public boolean isFirstRun() {
5467063a294955285efd6b3f038aafecc92293f803Paul Rohde        return mIsFirstRun;
5567063a294955285efd6b3f038aafecc92293f803Paul Rohde    }
5667063a294955285efd6b3f038aafecc92293f803Paul Rohde
5767063a294955285efd6b3f038aafecc92293f803Paul Rohde    /**
5867063a294955285efd6b3f038aafecc92293f803Paul Rohde     * Return true if this is the first time the app was opened.
5967063a294955285efd6b3f038aafecc92293f803Paul Rohde     */
6067063a294955285efd6b3f038aafecc92293f803Paul Rohde    public long getTimeOfFirstRun() {
6167063a294955285efd6b3f038aafecc92293f803Paul Rohde        return mTimeOfFirstRun;
6267063a294955285efd6b3f038aafecc92293f803Paul Rohde    }
6367063a294955285efd6b3f038aafecc92293f803Paul Rohde
6467063a294955285efd6b3f038aafecc92293f803Paul Rohde    /**
6567063a294955285efd6b3f038aafecc92293f803Paul Rohde     * Clear the first run flag.
6667063a294955285efd6b3f038aafecc92293f803Paul Rohde     */
6767063a294955285efd6b3f038aafecc92293f803Paul Rohde    public void clear() {
6867063a294955285efd6b3f038aafecc92293f803Paul Rohde        mIsFirstRun = false;
6967063a294955285efd6b3f038aafecc92293f803Paul Rohde    }
7067063a294955285efd6b3f038aafecc92293f803Paul Rohde
7167063a294955285efd6b3f038aafecc92293f803Paul Rohde    /**
7267063a294955285efd6b3f038aafecc92293f803Paul Rohde     * Returns time the app was first used, or UNKNOWN if the
7367063a294955285efd6b3f038aafecc92293f803Paul Rohde     * client is too old. This could be moved a separate utility class.
7467063a294955285efd6b3f038aafecc92293f803Paul Rohde     *
7567063a294955285efd6b3f038aafecc92293f803Paul Rohde     * @param context Application context.
7667063a294955285efd6b3f038aafecc92293f803Paul Rohde     */
7767063a294955285efd6b3f038aafecc92293f803Paul Rohde    public void initializeTimeOfFirstRun(Context context) {
78d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        mProfile.start();
79d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
8067063a294955285efd6b3f038aafecc92293f803Paul Rohde        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
81d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        mProfile.mark("PreferenceManager.getDefaultSharedPreferences");
8267063a294955285efd6b3f038aafecc92293f803Paul Rohde
8367063a294955285efd6b3f038aafecc92293f803Paul Rohde        // Read time of first installation.
8467063a294955285efd6b3f038aafecc92293f803Paul Rohde        long timeOfFirstUseMillis = preferences.getLong(CLIENT_FIRST_USE_TIME, 0);
85d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        mProfile.mark("preferences.getLong");
8667063a294955285efd6b3f038aafecc92293f803Paul Rohde
8767063a294955285efd6b3f038aafecc92293f803Paul Rohde        // Write installation time if not set.
8867063a294955285efd6b3f038aafecc92293f803Paul Rohde        if (timeOfFirstUseMillis == 0) {
8967063a294955285efd6b3f038aafecc92293f803Paul Rohde            SharedPreferences cameraPrefs = context.getSharedPreferences(
9067063a294955285efd6b3f038aafecc92293f803Paul Rohde                  context.getPackageName() + "_preferences_camera", Context.MODE_PRIVATE);
91d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde            mProfile.mark("getSharedPreferences");
92d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
9367063a294955285efd6b3f038aafecc92293f803Paul Rohde            // If we can find previous Shared Preferences, this is not a new install.
9467063a294955285efd6b3f038aafecc92293f803Paul Rohde            boolean isUpgrade = cameraPrefs.getAll().size() > 0 || preferences.getAll().size() > 0;
9567063a294955285efd6b3f038aafecc92293f803Paul Rohde
9667063a294955285efd6b3f038aafecc92293f803Paul Rohde            // Preference CLIENT_FIRST_USE_TIME is set to UNKNOWN for preference
9767063a294955285efd6b3f038aafecc92293f803Paul Rohde            // upgrades and the actual first use time for new installs.  We call
9867063a294955285efd6b3f038aafecc92293f803Paul Rohde            // System.currentTimeMillis() to match the log timebase.
9967063a294955285efd6b3f038aafecc92293f803Paul Rohde            timeOfFirstUseMillis = isUpgrade ? UNKNOWN : System.currentTimeMillis();
10067063a294955285efd6b3f038aafecc92293f803Paul Rohde            preferences.edit().putLong(CLIENT_FIRST_USE_TIME, timeOfFirstUseMillis).apply();
101d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde            mProfile.mark("preferences.edit()");
102d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
10367063a294955285efd6b3f038aafecc92293f803Paul Rohde            if (!isUpgrade) {
10467063a294955285efd6b3f038aafecc92293f803Paul Rohde                mIsFirstRun = true;
10567063a294955285efd6b3f038aafecc92293f803Paul Rohde            }
10667063a294955285efd6b3f038aafecc92293f803Paul Rohde        }
10767063a294955285efd6b3f038aafecc92293f803Paul Rohde        mTimeOfFirstRun = timeOfFirstUseMillis;
108d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        mProfile.stop();
10967063a294955285efd6b3f038aafecc92293f803Paul Rohde    }
11067063a294955285efd6b3f038aafecc92293f803Paul Rohde}