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.incallui.calllocation.impl;
18 
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.PackageManager;
23 import android.content.pm.ResolveInfo;
24 import android.database.Cursor;
25 import android.net.Uri;
26 import android.provider.Settings.Secure;
27 import android.provider.Settings.SettingNotFoundException;
28 import com.android.dialer.common.LogUtil;
29 
30 /**
31  * Helper class to check if Google Location Services is enabled. This class is based on
32  * https://docs.google.com/a/google.com/document/d/1sGm8pHgGY1QmxbLCwTZuWQASEDN7CFW9EPSZXAuGQfo
33  */
34 public class GoogleLocationSettingHelper {
35 
36   /** User has disagreed to use location for Google services. */
37   public static final int USE_LOCATION_FOR_SERVICES_OFF = 0;
38   /** User has agreed to use location for Google services. */
39   public static final int USE_LOCATION_FOR_SERVICES_ON = 1;
40   /** The user has neither agreed nor disagreed to use location for Google services yet. */
41   public static final int USE_LOCATION_FOR_SERVICES_NOT_SET = 2;
42 
43   private static final String GOOGLE_SETTINGS_AUTHORITY = "com.google.settings";
44   private static final Uri GOOGLE_SETTINGS_CONTENT_URI =
45       Uri.parse("content://" + GOOGLE_SETTINGS_AUTHORITY + "/partner");
46   private static final String NAME = "name";
47   private static final String VALUE = "value";
48   private static final String USE_LOCATION_FOR_SERVICES = "use_location_for_services";
49 
50   /** Determine if Google apps need to conform to the USE_LOCATION_FOR_SERVICES setting. */
isEnforceable(Context context)51   public static boolean isEnforceable(Context context) {
52     final ResolveInfo ri =
53         context
54             .getPackageManager()
55             .resolveActivity(
56                 new Intent("com.google.android.gsf.GOOGLE_APPS_LOCATION_SETTINGS"),
57                 PackageManager.MATCH_DEFAULT_ONLY);
58     return ri != null;
59   }
60 
61   /**
62    * Get the current value for the 'Use value for location' setting.
63    *
64    * @return One of {@link #USE_LOCATION_FOR_SERVICES_NOT_SET}, {@link
65    *     #USE_LOCATION_FOR_SERVICES_OFF} or {@link #USE_LOCATION_FOR_SERVICES_ON}.
66    */
getUseLocationForServices(Context context)67   private static int getUseLocationForServices(Context context) {
68     final ContentResolver resolver = context.getContentResolver();
69     Cursor c = null;
70     String stringValue = null;
71     try {
72       c =
73           resolver.query(
74               GOOGLE_SETTINGS_CONTENT_URI,
75               new String[] {VALUE},
76               NAME + "=?",
77               new String[] {USE_LOCATION_FOR_SERVICES},
78               null);
79       if (c != null && c.moveToNext()) {
80         stringValue = c.getString(0);
81       }
82     } catch (final RuntimeException e) {
83       LogUtil.e(
84           "GoogleLocationSettingHelper.getUseLocationForServices",
85           "Failed to get 'Use My Location' setting",
86           e);
87     } finally {
88       if (c != null) {
89         c.close();
90       }
91     }
92     if (stringValue == null) {
93       return USE_LOCATION_FOR_SERVICES_NOT_SET;
94     }
95     int value;
96     try {
97       value = Integer.parseInt(stringValue);
98     } catch (final NumberFormatException nfe) {
99       value = USE_LOCATION_FOR_SERVICES_NOT_SET;
100     }
101     return value;
102   }
103 
104   /** Whether or not the system location setting is enable */
isSystemLocationSettingEnabled(Context context)105   public static boolean isSystemLocationSettingEnabled(Context context) {
106     try {
107       return Secure.getInt(context.getContentResolver(), Secure.LOCATION_MODE)
108           != Secure.LOCATION_MODE_OFF;
109     } catch (SettingNotFoundException e) {
110       LogUtil.e(
111           "GoogleLocationSettingHelper.isSystemLocationSettingEnabled",
112           "Failed to get System Location setting",
113           e);
114       return false;
115     }
116   }
117 
118   /** Convenience method that returns true is GLS is ON or if it's not enforceable. */
isGoogleLocationServicesEnabled(Context context)119   public static boolean isGoogleLocationServicesEnabled(Context context) {
120     return !isEnforceable(context)
121         || getUseLocationForServices(context) == USE_LOCATION_FOR_SERVICES_ON;
122   }
123 }
124