1 /*
2  * Copyright (C) 2021 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.location;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.location.SettingInjectorService;
24 import android.os.UserHandle;
25 import android.util.Log;
26 
27 import androidx.annotation.VisibleForTesting;
28 import androidx.lifecycle.Lifecycle;
29 import androidx.lifecycle.OnLifecycleEvent;
30 import androidx.preference.Preference;
31 import androidx.preference.PreferenceScreen;
32 
33 import com.android.settings.Utils;
34 import com.android.settings.dashboard.DashboardFragment;
35 import com.android.settingslib.core.lifecycle.LifecycleObserver;
36 
37 import java.util.List;
38 import java.util.Map;
39 
40 /**
41  * A abstract class which is responsible for creating the injected location services items.
42  * Developer needs to implement the {@link #injectLocationServices(PreferenceScreen)}.
43  */
44 public abstract class LocationInjectedServiceBasePreferenceController
45         extends LocationBasePreferenceController implements LifecycleObserver{
46 
47     private static final String TAG = "LocationPrefCtrl";
48     @VisibleForTesting
49     static final IntentFilter INTENT_FILTER_INJECTED_SETTING_CHANGED =
50             new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED);
51 
52     @VisibleForTesting
53     AppSettingsInjector mInjector;
54     /** Receives UPDATE_INTENT */
55     @VisibleForTesting
56     BroadcastReceiver mInjectedSettingsReceiver;
57 
LocationInjectedServiceBasePreferenceController(Context context, String key)58     public LocationInjectedServiceBasePreferenceController(Context context, String key) {
59         super(context, key);
60     }
61 
62     @Override
init(DashboardFragment fragment)63     public void init(DashboardFragment fragment) {
64         super.init(fragment);
65         mInjector = new AppSettingsInjector(mContext, getMetricsCategory());
66     }
67 
68     @Override
displayPreference(PreferenceScreen screen)69     public void displayPreference(PreferenceScreen screen) {
70         super.displayPreference(screen);
71         injectLocationServices(screen);
72     }
73 
74     /**
75      * Override this method to inject location services in preference screen.
76      * @param screen
77      */
injectLocationServices(PreferenceScreen screen)78     protected abstract void injectLocationServices(PreferenceScreen screen);
79 
80     @Override
onLocationModeChanged(int mode, boolean restricted)81     public void onLocationModeChanged(int mode, boolean restricted) {
82         // As a safety measure, also reloads on location mode change to ensure the settings are
83         // up-to-date even if an affected app doesn't send the setting changed broadcast.
84         mInjector.reloadStatusMessages();
85     }
86 
87     /** @OnLifecycleEvent(ON_RESUME) */
88     @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
onResume()89     public void onResume() {
90         if (mInjectedSettingsReceiver == null) {
91             mInjectedSettingsReceiver = new BroadcastReceiver() {
92                 @Override
93                 public void onReceive(Context context, Intent intent) {
94                     if (Log.isLoggable(TAG, Log.DEBUG)) {
95                         Log.d(TAG, "Received settings change intent: " + intent);
96                     }
97                     mInjector.reloadStatusMessages();
98                 }
99             };
100         }
101         mContext.registerReceiver(
102                 mInjectedSettingsReceiver, INTENT_FILTER_INJECTED_SETTING_CHANGED);
103     }
104 
105     /** @OnLifecycleEvent(ON_PAUSE) */
106     @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
onPause()107     public void onPause() {
108         mContext.unregisterReceiver(mInjectedSettingsReceiver);
109     }
110 
getLocationServices()111     protected Map<Integer, List<Preference>> getLocationServices() {
112         // If location access is locked down by device policy then we only show injected settings
113         // for the primary profile.
114         final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
115 
116         return mInjector.getInjectedSettings(mFragment.getPreferenceManager().getContext(),
117                 (profileUserId != UserHandle.USER_NULL
118                         && mLocationEnabler.getShareLocationEnforcedAdmin(profileUserId) != null)
119                         ? UserHandle.myUserId() : UserHandle.USER_CURRENT);
120     }
121 }
122