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