• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 package com.android.permissioncontroller.permission.utils;
17 
18 import static android.location.LocationManager.EXTRA_LOCATION_ENABLED;
19 
20 import android.Manifest;
21 import android.app.AlertDialog;
22 import android.content.ActivityNotFoundException;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.DialogInterface.OnClickListener;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.location.LocationManager;
30 import android.os.Handler;
31 import android.os.Looper;
32 import android.os.UserHandle;
33 import android.provider.Settings;
34 import android.util.Log;
35 
36 import androidx.annotation.NonNull;
37 
38 import com.android.permissioncontroller.PermissionControllerApplication;
39 import com.android.permissioncontroller.R;
40 
41 import java.util.ArrayList;
42 
43 public class LocationUtils {
44 
45     public static final String LOCATION_PERMISSION = Manifest.permission_group.LOCATION;
46     public static final String ACTIVITY_RECOGNITION_PERMISSION =
47             Manifest.permission_group.ACTIVITY_RECOGNITION;
48 
49     private static final String TAG = LocationUtils.class.getSimpleName();
50     private static final long LOCATION_UPDATE_DELAY_MS = 1000;
51     private static final Handler sMainHandler = new Handler(Looper.getMainLooper());
52 
showLocationDialog(final Context context, CharSequence label)53     public static void showLocationDialog(final Context context, CharSequence label) {
54         new AlertDialog.Builder(context)
55                 .setIcon(R.drawable.ic_dialog_alert_material)
56                 .setTitle(android.R.string.dialog_alert_title)
57                 .setMessage(context.getString(R.string.location_warning, label))
58                 .setNegativeButton(R.string.ok, null)
59                 .setPositiveButton(R.string.location_settings, new OnClickListener() {
60                     @Override
61                     public void onClick(DialogInterface dialog, int which) {
62                         context.startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
63                     }
64                 })
65                 .show();
66     }
67 
68     /** Start the settings page for the location controller extra package. */
startLocationControllerExtraPackageSettings(@onNull Context context, @NonNull UserHandle user)69     public static void startLocationControllerExtraPackageSettings(@NonNull Context context,
70             @NonNull UserHandle user) {
71         try {
72             context.startActivityAsUser(new Intent(
73                         Settings.ACTION_LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS), user);
74         } catch (ActivityNotFoundException e) {
75             // In rare cases where location controller extra package is set, but
76             // no activity exists to handle the location controller extra package settings
77             // intent, log an error instead of crashing permission controller.
78             Log.e(TAG, "No activity to handle "
79                         + "android.settings.LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS");
80         }
81     }
82 
isLocationEnabled(Context context)83     public static boolean isLocationEnabled(Context context) {
84         return context.getSystemService(LocationManager.class).isLocationEnabled();
85     }
86 
isLocationGroupAndProvider(Context context, String groupName, String packageName)87     public static boolean isLocationGroupAndProvider(Context context, String groupName,
88             String packageName) {
89         return LOCATION_PERMISSION.equals(groupName)
90                 && context.getSystemService(LocationManager.class).isProviderPackage(packageName);
91     }
92 
isLocationGroupAndControllerExtraPackage(@onNull Context context, @NonNull String groupName, @NonNull String packageName)93     public static boolean isLocationGroupAndControllerExtraPackage(@NonNull Context context,
94             @NonNull String groupName, @NonNull String packageName) {
95         return (LOCATION_PERMISSION.equals(groupName)
96             || ACTIVITY_RECOGNITION_PERMISSION.equals(groupName))
97                 && packageName.equals(context.getSystemService(LocationManager.class)
98                         .getExtraLocationControllerPackage());
99     }
100 
101     /** Returns whether the location controller extra package is enabled. */
isExtraLocationControllerPackageEnabled(Context context)102     public static boolean isExtraLocationControllerPackageEnabled(Context context) {
103         try {
104             return context.getSystemService(LocationManager.class)
105                     .isExtraLocationControllerPackageEnabled();
106         } catch (Exception e) {
107             return false;
108         }
109 
110     }
111 
112     /**
113      * A Listener which responds to enabling or disabling of location on the device
114      */
115     public interface LocationListener {
116 
117         /**
118          * A callback run any time we receive a broadcast stating the location enable state has
119          * changed.
120          * @param enabled Whether or not location is enabled
121          */
onLocationStateChange(boolean enabled)122         void onLocationStateChange(boolean enabled);
123     }
124 
125     private static final ArrayList<LocationListener> sLocationListeners = new ArrayList<>();
126 
127     private static BroadcastReceiver sLocationBroadcastReceiver = new BroadcastReceiver() {
128         @Override
129         public void onReceive(Context context, Intent intent) {
130             boolean isEnabled = intent.getBooleanExtra(EXTRA_LOCATION_ENABLED, true);
131             sMainHandler.postDelayed(() -> {
132                 synchronized (sLocationListeners) {
133                     for (LocationListener l : sLocationListeners) {
134                         l.onLocationStateChange(isEnabled);
135                     }
136                 }
137             }, LOCATION_UPDATE_DELAY_MS);
138         }
139     };
140 
141     /**
142      * Add a LocationListener, which will be notified if the location provider is enabled or
143      * disabled
144      * @param listener the listener to add
145      */
addLocationListener(LocationListener listener)146     public static void addLocationListener(LocationListener listener) {
147         synchronized (sLocationListeners) {
148             boolean wasEmpty = sLocationListeners.isEmpty();
149             sLocationListeners.add(listener);
150             if (wasEmpty) {
151                 IntentFilter intentFilter = new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
152                 PermissionControllerApplication.get().getApplicationContext()
153                         .registerReceiverForAllUsers(sLocationBroadcastReceiver, intentFilter,
154                                 null, null);
155             }
156         }
157     }
158 
159     /**
160      * Remove a LocationListener
161      * @param listener The listener to remove
162      *
163      * @return True if it was successfully removed, false otherwise
164      */
removeLocationListener(LocationListener listener)165     public static boolean removeLocationListener(LocationListener listener) {
166         synchronized (sLocationListeners) {
167             boolean success = sLocationListeners.remove(listener);
168             if (success && sLocationListeners.isEmpty()) {
169                 PermissionControllerApplication.get().getApplicationContext()
170                         .unregisterReceiver(sLocationBroadcastReceiver);
171             }
172             return success;
173         }
174     }
175 }
176