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}