146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file. 446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)package org.chromium.chrome.browser.util; 646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.annotation.SuppressLint; 846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.annotation.TargetApi; 946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.content.Context; 1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.content.Intent; 1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.content.pm.PackageManager; 1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.content.pm.ResolveInfo; 1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.os.Build; 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.os.Bundle; 1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.os.UserManager; 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import android.speech.RecognizerIntent; 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import com.google.common.annotations.VisibleForTesting; 1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import org.chromium.base.ThreadUtils; 2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import org.chromium.sync.signin.AccountManagerHelper; 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import java.util.List; 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/** 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * A utility {@code class} meant to help determine whether or not certain features are supported by 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * this device. 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) */ 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)public class FeatureUtilities { 3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private static Boolean sHasGoogleAccountAuthenticator; 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private static Boolean sHasRecognitionIntentHandler; 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) /** 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * Determines whether or not the {@link RecognizerIntent#ACTION_WEB_SEARCH} {@link Intent} 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * is handled by any {@link android.app.Activity}s in the system. The result will be cached for 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * future calls. Passing {@code false} to {@code useCachedValue} will force it to re-query any 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * {@link android.app.Activity}s that can process the {@link Intent}. 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @param context The {@link Context} to use to check to see if the {@link Intent} will 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * be handled. 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @param useCachedValue Whether or not to use the cached value from a previous result. 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @return {@code true} if recognition is supported. {@code false} otherwise. 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) */ 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public static boolean isRecognitionIntentPresent(Context context, boolean useCachedValue) { 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ThreadUtils.assertOnUiThread(); 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (sHasRecognitionIntentHandler == null || !useCachedValue) { 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PackageManager pm = context.getPackageManager(); 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) List<ResolveInfo> activities = pm.queryIntentActivities( 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0); 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) sHasRecognitionIntentHandler = activities.size() > 0; 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return sHasRecognitionIntentHandler; 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) /** 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * Determines whether or not the user has a Google account (so we can sync) or can add one. 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @param context The {@link Context} that we should check accounts under. 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @return Whether or not sync is allowed on this device. 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) */ 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public static boolean canAllowSync(Context context) { 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return (hasGoogleAccountAuthenticator(context) && hasSyncPermissions(context)) || 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) hasGoogleAccounts(context); 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) @VisibleForTesting 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static boolean hasGoogleAccountAuthenticator(Context context) { 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (sHasGoogleAccountAuthenticator == null) { 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) AccountManagerHelper accountHelper = AccountManagerHelper.get(context); 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) sHasGoogleAccountAuthenticator = accountHelper.hasGoogleAccountAuthenticator(); 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return sHasGoogleAccountAuthenticator; 7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) @VisibleForTesting 7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static boolean hasGoogleAccounts(Context context) { 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return AccountManagerHelper.get(context).hasGoogleAccounts(); 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) @SuppressLint("InlinedApi") 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private static boolean hasSyncPermissions(Context context) { 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) return true; 8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UserManager manager = (UserManager) context.getSystemService(Context.USER_SERVICE); 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Bundle userRestrictions = manager.getUserRestrictions(); 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return !userRestrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false); 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 89