1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera.app;
18
19import android.content.Context;
20import android.content.SharedPreferences;
21import android.preference.PreferenceManager;
22
23import com.android.camera.stats.profiler.Profile;
24import com.android.camera.stats.profiler.Profiler;
25import com.android.camera.stats.profiler.Profilers;
26
27public class FirstRunDetector {
28    private static final long UNKNOWN = -1;
29    // Default SharedPreferences key for when the application was first used.
30    private static final String CLIENT_FIRST_USE_TIME = "client_first_use_time_millis";
31
32    private static class Singleton {
33        private static final FirstRunDetector INSTANCE = new FirstRunDetector(
34              Profilers.instance().guard());
35    }
36
37    public static FirstRunDetector instance() {
38        return Singleton.INSTANCE;
39    }
40
41    private final Profile mProfile;
42    private long mTimeOfFirstRun;
43    /** Flag set to true if and only if first run of application is detected. */
44    private boolean mIsFirstRun = false;
45
46    private FirstRunDetector(Profiler profiler) {
47        mProfile = profiler.create("FirstRunDetector getTimeOfFirstRun");
48    }
49
50    /**
51     * Return true if this is the first time the app was opened.
52     */
53    public boolean isFirstRun() {
54        return mIsFirstRun;
55    }
56
57    /**
58     * Return true if this is the first time the app was opened.
59     */
60    public long getTimeOfFirstRun() {
61        return mTimeOfFirstRun;
62    }
63
64    /**
65     * Clear the first run flag.
66     */
67    public void clear() {
68        mIsFirstRun = false;
69    }
70
71    /**
72     * Returns time the app was first used, or UNKNOWN if the
73     * client is too old. This could be moved a separate utility class.
74     *
75     * @param context Application context.
76     */
77    public void initializeTimeOfFirstRun(Context context) {
78        mProfile.start();
79
80        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
81        mProfile.mark("PreferenceManager.getDefaultSharedPreferences");
82
83        // Read time of first installation.
84        long timeOfFirstUseMillis = preferences.getLong(CLIENT_FIRST_USE_TIME, 0);
85        mProfile.mark("preferences.getLong");
86
87        // Write installation time if not set.
88        if (timeOfFirstUseMillis == 0) {
89            SharedPreferences cameraPrefs = context.getSharedPreferences(
90                  context.getPackageName() + "_preferences_camera", Context.MODE_PRIVATE);
91            mProfile.mark("getSharedPreferences");
92
93            // If we can find previous Shared Preferences, this is not a new install.
94            boolean isUpgrade = cameraPrefs.getAll().size() > 0 || preferences.getAll().size() > 0;
95
96            // Preference CLIENT_FIRST_USE_TIME is set to UNKNOWN for preference
97            // upgrades and the actual first use time for new installs.  We call
98            // System.currentTimeMillis() to match the log timebase.
99            timeOfFirstUseMillis = isUpgrade ? UNKNOWN : System.currentTimeMillis();
100            preferences.edit().putLong(CLIENT_FIRST_USE_TIME, timeOfFirstUseMillis).apply();
101            mProfile.mark("preferences.edit()");
102
103            if (!isUpgrade) {
104                mIsFirstRun = true;
105            }
106        }
107        mTimeOfFirstRun = timeOfFirstUseMillis;
108        mProfile.stop();
109    }
110}