1 /* 2 * Copyright (C) 2017 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.settings.support; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.SharedPreferences; 23 import android.content.pm.PackageInfo; 24 import android.content.pm.PackageManager; 25 import android.content.pm.ResolveInfo; 26 import android.net.Uri; 27 import android.os.Bundle; 28 import android.support.annotation.NonNull; 29 import android.support.annotation.VisibleForTesting; 30 import android.text.TextUtils; 31 import android.text.format.DateUtils; 32 import android.util.Log; 33 34 import com.android.settings.R; 35 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider; 36 import com.android.settings.overlay.FeatureFactory; 37 import com.android.settings.overlay.SupportFeatureProvider; 38 39 import java.util.List; 40 41 public class NewDeviceIntroSuggestionActivity extends Activity { 42 43 private static final String TAG = "NewDeviceIntroSugg"; 44 @VisibleForTesting 45 static final String PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME = 46 "pref_new_device_intro_suggestion_first_display_time_ms"; 47 @VisibleForTesting 48 static final String PREF_KEY_SUGGGESTION_COMPLETE = 49 "pref_new_device_intro_suggestion_complete"; 50 @VisibleForTesting 51 static final long PERMANENT_DISMISS_THRESHOLD = DateUtils.DAY_IN_MILLIS * 14; 52 53 public static final String TIPS_PACKAGE_NAME = "com.google.android.apps.tips"; 54 55 @Override onCreate(Bundle savedInstanceState)56 protected void onCreate(Bundle savedInstanceState) { 57 super.onCreate(savedInstanceState); 58 final Intent intent = getLaunchIntent(this); 59 if (intent != null) { 60 final SuggestionFeatureProvider featureProvider = FeatureFactory.getFactory(this) 61 .getSuggestionFeatureProvider(this); 62 final SharedPreferences prefs = featureProvider.getSharedPrefs(this); 63 prefs.edit().putBoolean(PREF_KEY_SUGGGESTION_COMPLETE, true).commit(); 64 startActivity(intent); 65 } 66 finish(); 67 } 68 isSuggestionComplete(Context context)69 public static boolean isSuggestionComplete(Context context) { 70 // Always returns 'true' if Tips application exists. Check b/77652536 for more details. 71 return isTipsInstalledAsSystemApp(context) 72 || !isSupported(context) 73 || isExpired(context) 74 || hasLaunchedBefore(context) 75 || !canOpenUrlInBrowser(context); 76 } 77 isSupported(Context context)78 private static boolean isSupported(Context context) { 79 return context.getResources() 80 .getBoolean(R.bool.config_new_device_intro_suggestion_supported); 81 } 82 isExpired(Context context)83 private static boolean isExpired(Context context) { 84 final SuggestionFeatureProvider featureProvider = FeatureFactory.getFactory(context) 85 .getSuggestionFeatureProvider(context); 86 final SharedPreferences prefs = featureProvider.getSharedPrefs(context); 87 final long currentTimeMs = System.currentTimeMillis(); 88 final long firstDisplayTimeMs; 89 90 if (!prefs.contains(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME)) { 91 firstDisplayTimeMs = currentTimeMs; 92 prefs.edit().putLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME, currentTimeMs).commit(); 93 } else { 94 firstDisplayTimeMs = prefs.getLong(PREF_KEY_SUGGGESTION_FIRST_DISPLAY_TIME, -1); 95 } 96 97 final long dismissTimeMs = firstDisplayTimeMs + PERMANENT_DISMISS_THRESHOLD; 98 99 final boolean expired = currentTimeMs > dismissTimeMs; 100 101 Log.d(TAG, "is suggestion expired: " + expired); 102 return expired; 103 } 104 canOpenUrlInBrowser(Context context)105 private static boolean canOpenUrlInBrowser(Context context) { 106 final Intent intent = getLaunchIntent(context); 107 if (intent == null) { 108 // No url/intent to launch. 109 return false; 110 } 111 // Make sure we can handle the intent. 112 final List<ResolveInfo> resolveInfos = 113 context.getPackageManager().queryIntentActivities(intent, 0); 114 return resolveInfos != null && resolveInfos.size() != 0; 115 } 116 hasLaunchedBefore(Context context)117 private static boolean hasLaunchedBefore(Context context) { 118 final SuggestionFeatureProvider featureProvider = FeatureFactory.getFactory(context) 119 .getSuggestionFeatureProvider(context); 120 final SharedPreferences prefs = featureProvider.getSharedPrefs(context); 121 return prefs.getBoolean(PREF_KEY_SUGGGESTION_COMPLETE, false); 122 } 123 124 @VisibleForTesting getLaunchIntent(Context context)125 static Intent getLaunchIntent(Context context) { 126 final SupportFeatureProvider supportProvider = FeatureFactory.getFactory(context) 127 .getSupportFeatureProvider(context); 128 if (supportProvider == null) { 129 return null; 130 } 131 final String url = supportProvider.getNewDeviceIntroUrl(context); 132 if (TextUtils.isEmpty(url)) { 133 return null; 134 } 135 return new Intent() 136 .setAction(Intent.ACTION_VIEW) 137 .addCategory(Intent.CATEGORY_BROWSABLE) 138 .setData(Uri.parse(url)); 139 } 140 141 /** 142 * Check if the specified package exists and is marked with <i>FLAG_SYSTEM</i> 143 */ isTipsInstalledAsSystemApp(@onNull Context context)144 private static boolean isTipsInstalledAsSystemApp(@NonNull Context context) { 145 try { 146 final PackageInfo info = context.getPackageManager().getPackageInfo(TIPS_PACKAGE_NAME, 147 PackageManager.MATCH_SYSTEM_ONLY); 148 return info != null; 149 } catch (PackageManager.NameNotFoundException e) { 150 Log.w(TAG, "Cannot find the package: " + TIPS_PACKAGE_NAME, e); 151 return false; 152 } 153 } 154 } 155