• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.car.settings;
18 
19 import static android.car.CarOccupantZoneManager.DISPLAY_TYPE_MAIN;
20 
21 import android.annotation.Nullable;
22 import android.app.Application;
23 import android.car.Car;
24 import android.car.Car.CarServiceLifecycleListener;
25 import android.car.CarOccupantZoneManager;
26 import android.car.CarOccupantZoneManager.OccupantZoneConfigChangeListener;
27 import android.car.CarOccupantZoneManager.OccupantZoneInfo;
28 import android.car.media.CarAudioManager;
29 import android.car.wifi.CarWifiManager;
30 import android.content.BroadcastReceiver;
31 import android.content.ComponentName;
32 import android.content.Context;
33 import android.content.Intent;
34 import android.content.IntentFilter;
35 import android.content.pm.PackageManager;
36 import android.os.UserManager;
37 import android.view.Display;
38 
39 import androidx.annotation.GuardedBy;
40 import androidx.annotation.VisibleForTesting;
41 
42 import com.android.car.settings.activityembedding.ActivityEmbeddingRulesController;
43 import com.android.car.settings.activityembedding.ActivityEmbeddingUtils;
44 import com.android.car.settings.common.Logger;
45 import com.android.car.settings.deeplink.DeepLinkHomepageActivity;
46 
47 /**
48  * Application class for CarSettings.
49  */
50 public class CarSettingsApplication extends Application {
51 
52     public static final String CAR_SETTINGS_PACKAGE_NAME = "com.android.car.settings";
53     private static final Logger LOG = new Logger(CarSettingsApplication.class);
54     private CarOccupantZoneManager mCarOccupantZoneManager;
55 
56     private final Object mInfoLock = new Object();
57     private final Object mCarAudioManagerLock = new Object();
58     private final Object mCarWifiManagerLock = new Object();
59 
60     @GuardedBy("mInfoLock")
61     private int mOccupantZoneDisplayId = Display.DEFAULT_DISPLAY;
62     @GuardedBy("mInfoLock")
63     private int mAudioZoneId = CarAudioManager.INVALID_AUDIO_ZONE;
64     @GuardedBy("mInfoLock")
65     private int mOccupantZoneType = CarOccupantZoneManager.OCCUPANT_TYPE_INVALID;
66     @GuardedBy("mCarAudioManagerLock")
67     private CarAudioManager mCarAudioManager = null;
68     @GuardedBy("mCarWifiManagerLock")
69     private CarWifiManager mCarWifiManager = null;
70 
71     /**
72      * Listener to monitor any Occupant Zone configuration change.
73      */
74     private final OccupantZoneConfigChangeListener mConfigChangeListener = flags -> {
75         synchronized (mInfoLock) {
76             updateZoneInfoLocked();
77         }
78     };
79 
80     /**
81      * Listener to monitor the Lifecycle of car service.
82      */
83     private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> {
84         if (!ready) {
85             mCarOccupantZoneManager = null;
86             synchronized (mCarAudioManagerLock) {
87                 mCarAudioManager = null;
88             }
89             synchronized (mCarWifiManagerLock) {
90                 mCarWifiManager = null;
91             }
92             return;
93         }
94         mCarOccupantZoneManager = (CarOccupantZoneManager) car.getCarManager(
95                 Car.CAR_OCCUPANT_ZONE_SERVICE);
96         if (mCarOccupantZoneManager != null) {
97             mCarOccupantZoneManager.registerOccupantZoneConfigChangeListener(
98                     mConfigChangeListener);
99         }
100         synchronized (mCarAudioManagerLock) {
101             mCarAudioManager = (CarAudioManager) car.getCarManager(Car.AUDIO_SERVICE);
102         }
103         synchronized (mCarWifiManagerLock) {
104             mCarWifiManager = (CarWifiManager) car.getCarManager(Car.CAR_WIFI_SERVICE);
105         }
106         synchronized (mInfoLock) {
107             updateZoneInfoLocked();
108         }
109     };
110 
111     @Override
onCreate()112     public void onCreate() {
113         super.onCreate();
114         registerCarServiceLifecycleListener();
115         // Register activity embedding only when user is unlocked, which happens after boot has been
116         // completed. This is so that RRO values may be read properly for device configurations that
117         // uses RROs for embedding related configs, which are not available before boot completion.
118         ActivityEmbeddingRulesController controller = new ActivityEmbeddingRulesController(this);
119         if (getApplicationContext().getSystemService(UserManager.class).isUserUnlocked()) {
120             controller.initActivityEmbeddingRules();
121         } else {
122             IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
123             getApplicationContext().registerReceiver(new BroadcastReceiver() {
124                 @Override
125                 public void onReceive(Context context, Intent intent) {
126                     controller.initActivityEmbeddingRules();
127                 }
128             }, filter, 0);
129         }
130         updateDeepLinkHomepageActivityEnabledState();
131     }
132 
133     @VisibleForTesting
registerCarServiceLifecycleListener()134     void registerCarServiceLifecycleListener() {
135         Car.createCar(this, /* handler= */ null , Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER,
136                 mCarServiceLifecycleListener);
137     }
138 
139     /**
140      * Returns zone type assigned for the current user.
141      * The zone type is used to determine whether the settings preferences
142      * should be available or not.
143      */
getMyOccupantZoneType()144     public final int getMyOccupantZoneType() {
145         synchronized (mInfoLock) {
146             return mOccupantZoneType;
147         }
148     }
149 
150     /**
151      * Returns displayId assigned for the current user.
152      */
getMyOccupantZoneDisplayId()153     public final int getMyOccupantZoneDisplayId() {
154         synchronized (mInfoLock) {
155             return mOccupantZoneDisplayId;
156         }
157     }
158 
159     /**
160      * Returns audio zone id assigned for the current user.
161      */
getMyAudioZoneId()162     public final int getMyAudioZoneId() {
163         synchronized (mInfoLock) {
164             return mAudioZoneId;
165         }
166     }
167 
168     /**
169      * Returns CarAudioManager instance.
170      */
171     @Nullable
getCarAudioManager()172     public final CarAudioManager getCarAudioManager() {
173         synchronized (mCarAudioManagerLock) {
174             return mCarAudioManager;
175         }
176     }
177 
178     /**
179      * Returns CarAudioManager instance.
180      */
181     @Nullable
getCarWifiManager()182     public final CarWifiManager getCarWifiManager() {
183         synchronized (mCarWifiManagerLock) {
184             return mCarWifiManager;
185         }
186     }
187 
188     @GuardedBy("mInfoLock")
updateZoneInfoLocked()189     private void updateZoneInfoLocked() {
190         if (mCarOccupantZoneManager == null) {
191             return;
192         }
193         OccupantZoneInfo info = mCarOccupantZoneManager.getMyOccupantZone();
194         if (info != null) {
195             mOccupantZoneType = info.occupantType;
196             mAudioZoneId = mCarOccupantZoneManager.getAudioZoneIdForOccupant(info);
197             Display display = mCarOccupantZoneManager
198                     .getDisplayForOccupant(info, DISPLAY_TYPE_MAIN);
199             if (display != null) {
200                 mOccupantZoneDisplayId = display.getDisplayId();
201             }
202         }
203     }
204 
205     /**
206      * Disable {@link DeepLinkHomepageActivity} if ActivityEmbedding is not enabled.
207      */
updateDeepLinkHomepageActivityEnabledState()208     private void updateDeepLinkHomepageActivityEnabledState() {
209         int componentEnabledState = ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this)
210                 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
211                 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
212         try {
213             getPackageManager().setComponentEnabledSetting(
214                     /* ComponentName */ new ComponentName(this, DeepLinkHomepageActivity.class),
215                     /* newState */ componentEnabledState,
216                     /* flags */ PackageManager.DONT_KILL_APP);
217         } catch (IllegalArgumentException exception) {
218             LOG.e("Unable to update enabled state for DeepLinkHomepageActivity: " + exception);
219         }
220     }
221 }
222