Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2014 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 
     17 package com.android.inputmethod.latin.utils;
     18 
     19 import android.Manifest;
     20 import android.content.Context;
     21 import android.content.SharedPreferences;
     22 import android.provider.Settings;
     23 import android.provider.Settings.SettingNotFoundException;
     24 import android.text.TextUtils;
     25 import android.util.Log;
     26 
     27 import com.android.inputmethod.annotations.UsedForTesting;
     28 import com.android.inputmethod.latin.R;
     29 import com.android.inputmethod.latin.permissions.PermissionsUtil;
     30 import com.android.inputmethod.latin.settings.SettingsValues;
     31 
     32 import java.util.concurrent.TimeUnit;
     33 
     34 public final class ImportantNoticeUtils {
     35     private static final String TAG = ImportantNoticeUtils.class.getSimpleName();
     36 
     37     // {@link SharedPreferences} name to save the last important notice version that has been
     38     // displayed to users.
     39     private static final String PREFERENCE_NAME = "important_notice_pref";
     40 
     41     private static final String KEY_SUGGEST_CONTACTS_NOTICE = "important_notice_suggest_contacts";
     42 
     43     @UsedForTesting
     44     static final String KEY_TIMESTAMP_OF_CONTACTS_NOTICE = "timestamp_of_suggest_contacts_notice";
     45 
     46     @UsedForTesting
     47     static final long TIMEOUT_OF_IMPORTANT_NOTICE = TimeUnit.HOURS.toMillis(23);
     48 
     49     // Copy of the hidden {@link Settings.Secure#USER_SETUP_COMPLETE} settings key.
     50     // The value is zero until each multiuser completes system setup wizard.
     51     // Caveat: This is a hidden API.
     52     private static final String Settings_Secure_USER_SETUP_COMPLETE = "user_setup_complete";
     53     private static final int USER_SETUP_IS_NOT_COMPLETE = 0;
     54 
     55     private ImportantNoticeUtils() {
     56         // This utility class is not publicly instantiable.
     57     }
     58 
     59     @UsedForTesting
     60     static boolean isInSystemSetupWizard(final Context context) {
     61         try {
     62             final int userSetupComplete = Settings.Secure.getInt(
     63                     context.getContentResolver(), Settings_Secure_USER_SETUP_COMPLETE);
     64             return userSetupComplete == USER_SETUP_IS_NOT_COMPLETE;
     65         } catch (final SettingNotFoundException e) {
     66             Log.w(TAG, "Can't find settings in Settings.Secure: key="
     67                     + Settings_Secure_USER_SETUP_COMPLETE);
     68             return false;
     69         }
     70     }
     71 
     72     @UsedForTesting
     73     static SharedPreferences getImportantNoticePreferences(final Context context) {
     74         return context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
     75     }
     76 
     77     @UsedForTesting
     78     static boolean hasContactsNoticeShown(final Context context) {
     79         return getImportantNoticePreferences(context).getBoolean(
     80                 KEY_SUGGEST_CONTACTS_NOTICE, false);
     81     }
     82 
     83     public static boolean shouldShowImportantNotice(final Context context,
     84             final SettingsValues settingsValues) {
     85         // Check to see whether "Use Contacts" is enabled by the user.
     86         if (!settingsValues.mUseContactsDict) {
     87             return false;
     88         }
     89 
     90         if (hasContactsNoticeShown(context)) {
     91             return false;
     92         }
     93 
     94         // Don't show the dialog if we have all the permissions.
     95         if (PermissionsUtil.checkAllPermissionsGranted(
     96                 context, Manifest.permission.READ_CONTACTS)) {
     97             return false;
     98         }
     99 
    100         final String importantNoticeTitle = getSuggestContactsNoticeTitle(context);
    101         if (TextUtils.isEmpty(importantNoticeTitle)) {
    102             return false;
    103         }
    104         if (isInSystemSetupWizard(context)) {
    105             return false;
    106         }
    107         if (hasContactsNoticeTimeoutPassed(context, System.currentTimeMillis())) {
    108             updateContactsNoticeShown(context);
    109             return false;
    110         }
    111         return true;
    112     }
    113 
    114     public static String getSuggestContactsNoticeTitle(final Context context) {
    115         return context.getResources().getString(R.string.important_notice_suggest_contact_names);
    116     }
    117 
    118     @UsedForTesting
    119     static boolean hasContactsNoticeTimeoutPassed(
    120             final Context context, final long currentTimeInMillis) {
    121         final SharedPreferences prefs = getImportantNoticePreferences(context);
    122         if (!prefs.contains(KEY_TIMESTAMP_OF_CONTACTS_NOTICE)) {
    123             prefs.edit()
    124                     .putLong(KEY_TIMESTAMP_OF_CONTACTS_NOTICE, currentTimeInMillis)
    125                     .apply();
    126         }
    127         final long firstDisplayTimeInMillis = prefs.getLong(
    128                 KEY_TIMESTAMP_OF_CONTACTS_NOTICE, currentTimeInMillis);
    129         final long elapsedTime = currentTimeInMillis - firstDisplayTimeInMillis;
    130         return elapsedTime >= TIMEOUT_OF_IMPORTANT_NOTICE;
    131     }
    132 
    133     public static void updateContactsNoticeShown(final Context context) {
    134         getImportantNoticePreferences(context)
    135                 .edit()
    136                 .putBoolean(KEY_SUGGEST_CONTACTS_NOTICE, true)
    137                 .remove(KEY_TIMESTAMP_OF_CONTACTS_NOTICE)
    138                 .apply();
    139     }
    140 }
    141