• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.server.uwb;
18 
19 import android.content.Context;
20 import android.os.Handler;
21 import android.provider.DeviceConfig;
22 import android.util.Log;
23 
24 import com.android.uwb.resources.R;
25 
26 /**
27  * This class allows getting all configurable flags from DeviceConfig.
28  */
29 public class DeviceConfigFacade {
30     private static final String LOG_TAG = DeviceConfigFacade.class.getSimpleName();
31 
32     /**
33      */
34     private static final int MAX_FOV = 180;
35 
36     public static final int DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS = 5_000;
37     private static final int MS_IN_HOUR = 60 * 60 * 1000;
38     public static final int DEFAULT_BUG_REPORT_MIN_INTERVAL_MS = 24 * MS_IN_HOUR;
39     private static final String TAG = "DeviceConfigFacadeUwb";
40 
41     public enum PoseSourceType {
42         NONE,
43         ROTATION_VECTOR,
44         GYRO,
45         SIXDOF,
46         DOUBLE_INTEGRATE,
47     }
48 
49     private final Context mContext;
50 
51     // Cached values of fields updated via updateDeviceConfigFlags()
52     private int mRangingResultLogIntervalMs;
53     private boolean mDeviceErrorBugreportEnabled;
54     private boolean mSessionInitErrorBugreportEnabled;
55     private int mBugReportMinIntervalMs;
56     private boolean mEnableFilters;
57     private int mFilterDistanceInliersPercent;
58     private int mFilterDistanceWindow;
59     private int mFilterAngleInliersPercent;
60     private int mFilterAngleWindow;
61     private PoseSourceType mPoseSourceType;
62     private boolean mEnablePrimerEstElevation;
63     private boolean mEnablePrimerAoA;
64     private boolean mEnablePrimerFov;
65     private int mPrimerFovDegree;
66     private boolean mEnableBackAzimuth;
67     private boolean mEnableBackAzimuthMasking;
68     private int mBackAzimuthWindow;
69     private float mFrontAzimuthRadiansPerSecond;
70     private float mBackAzimuthRadiansPerSecond;
71     private float mMirrorScoreStdRadians;
72     private float mBackNoiseInfluenceCoeff;
73     private int mPredictionTimeoutSeconds;
74 
75     // Config parameters related to Advertising Profile.
76     private int mAdvertiseAoaCriteriaAngle;
77     private int mAdvertiseTimeThresholdMillis;
78     private int mAdvertiseArraySizeToCheck;
79     private int mAdvertiseArrayStartIndexToCalVariance;
80     private int mAdvertiseArrayEndIndexToCalVariance;
81     private int mAdvertiseTrustedVarianceValue;
82 
83     // Config parameters related to Rx/Tx data packets.
84     private int mRxDataMaxPacketsToStore;
85     // Flag to enable unlimited background ranging.
86     private boolean mBackgroundRangingEnabled;
87     // Flag to disable error streak timer when a session is ongoing.
88     private boolean mRangingErrorStreakTimerEnabled;
89 
DeviceConfigFacade(Handler handler, Context context)90     public DeviceConfigFacade(Handler handler, Context context) {
91         mContext = context;
92 
93         updateDeviceConfigFlags();
94         DeviceConfig.addOnPropertiesChangedListener(
95                 DeviceConfig.NAMESPACE_UWB,
96                 command -> handler.post(command),
97                 properties -> {
98                     updateDeviceConfigFlags();
99                 });
100     }
101 
updateDeviceConfigFlags()102     private void updateDeviceConfigFlags() {
103         String poseSourceName;
104         mRangingResultLogIntervalMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_UWB,
105                 "ranging_result_log_interval_ms", DEFAULT_RANGING_RESULT_LOG_INTERVAL_MS);
106         mDeviceErrorBugreportEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_UWB,
107                 "device_error_bugreport_enabled", false);
108         mSessionInitErrorBugreportEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_UWB,
109                 "session_init_error_bugreport_enabled", false);
110         mBugReportMinIntervalMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_UWB,
111                 "bug_report_min_interval_ms", DEFAULT_BUG_REPORT_MIN_INTERVAL_MS);
112 
113         // Default values come from the overlay file (config.xml).
114         mEnableFilters = DeviceConfig.getBoolean(
115                 DeviceConfig.NAMESPACE_UWB,
116                 "enable_filters",
117                 mContext.getResources().getBoolean(R.bool.enable_filters)
118         );
119         mFilterDistanceInliersPercent = DeviceConfig.getInt(
120                 DeviceConfig.NAMESPACE_UWB,
121                 "filter_distance_inliers_percent",
122                 mContext.getResources().getInteger(R.integer.filter_distance_inliers_percent)
123         );
124         mFilterDistanceWindow = DeviceConfig.getInt(
125                 DeviceConfig.NAMESPACE_UWB,
126                 "filter_distance_window",
127                 mContext.getResources().getInteger(R.integer.filter_distance_window)
128         );
129         mFilterAngleInliersPercent = DeviceConfig.getInt(
130                 DeviceConfig.NAMESPACE_UWB,
131                 "filter_angle_inliers_percent",
132                 mContext.getResources().getInteger(R.integer.filter_angle_inliers_percent)
133         );
134         mFilterAngleWindow = DeviceConfig.getInt(
135                 DeviceConfig.NAMESPACE_UWB,
136                 "filter_angle_window",
137                 mContext.getResources().getInteger(R.integer.filter_angle_window)
138         );
139         poseSourceName = DeviceConfig.getString(
140                 DeviceConfig.NAMESPACE_UWB,
141                 "pose_source_type",
142                 mContext.getResources().getString(R.string.pose_source_type)
143         );
144         mEnablePrimerEstElevation = DeviceConfig.getBoolean(
145                 DeviceConfig.NAMESPACE_UWB,
146                 "enable_primer_est_elevation",
147                 mContext.getResources().getBoolean(R.bool.enable_primer_est_elevation)
148         );
149         mEnablePrimerAoA = DeviceConfig.getBoolean(
150                 DeviceConfig.NAMESPACE_UWB,
151                 "enable_primer_aoa",
152                 mContext.getResources().getBoolean(R.bool.enable_primer_aoa)
153         );
154         mPrimerFovDegree = DeviceConfig.getInt(
155                 DeviceConfig.NAMESPACE_UWB,
156                 "primer_fov_degrees",
157                 mContext.getResources().getInteger(R.integer.primer_fov_degrees)
158         );
159         mPredictionTimeoutSeconds = DeviceConfig.getInt(
160                 DeviceConfig.NAMESPACE_UWB,
161                 "prediction_timeout_seconds",
162                 mContext.getResources().getInteger(R.integer.prediction_timeout_seconds)
163         );
164         mEnableBackAzimuth = DeviceConfig.getBoolean(
165                 DeviceConfig.NAMESPACE_UWB,
166                 "enable_azimuth_mirroring",
167                 mContext.getResources().getBoolean(R.bool.enable_azimuth_mirroring)
168         );
169         mEnableBackAzimuthMasking = DeviceConfig.getBoolean(
170                 DeviceConfig.NAMESPACE_UWB,
171                 "predict_rear_azimuths",
172                 mContext.getResources().getBoolean(R.bool.predict_rear_azimuths)
173         );
174         mBackAzimuthWindow = DeviceConfig.getInt(
175                 DeviceConfig.NAMESPACE_UWB,
176                 "mirror_detection_window",
177                 mContext.getResources().getInteger(R.integer.mirror_detection_window)
178         );
179         int frontAzimuthDegreesPerSecond = DeviceConfig.getInt(
180                 DeviceConfig.NAMESPACE_UWB,
181                 "front_mirror_dps",
182                 mContext.getResources().getInteger(R.integer.front_mirror_dps)
183         );
184         int backAzimuthDegreesPerSecond = DeviceConfig.getInt(
185                 DeviceConfig.NAMESPACE_UWB,
186                 "back_mirror_dps",
187                 mContext.getResources().getInteger(R.integer.back_mirror_dps)
188         );
189         int mirrorScoreStdDegrees = DeviceConfig.getInt(
190                 DeviceConfig.NAMESPACE_UWB,
191                 "mirror_score_std_degrees",
192                 mContext.getResources().getInteger(R.integer.mirror_score_std_degrees)
193         );
194         int backNoiseInfluencePercent = DeviceConfig.getInt(
195                 DeviceConfig.NAMESPACE_UWB,
196                 "back_noise_influence_percent",
197                 mContext.getResources().getInteger(R.integer.back_noise_influence_percent)
198         );
199 
200         // Read the Advertising profile config parameters.
201         mAdvertiseAoaCriteriaAngle = DeviceConfig.getInt(
202                 DeviceConfig.NAMESPACE_UWB,
203                 "advertise_aoa_criteria_angle",
204                 mContext.getResources().getInteger(R.integer.advertise_aoa_criteria_angle)
205         );
206         mAdvertiseTimeThresholdMillis = DeviceConfig.getInt(
207                 DeviceConfig.NAMESPACE_UWB,
208                 "advertise_time_threshold_millis",
209                 mContext.getResources().getInteger(R.integer.advertise_time_threshold_millis)
210         );
211         mAdvertiseArraySizeToCheck = DeviceConfig.getInt(
212                 DeviceConfig.NAMESPACE_UWB,
213                 "advertise_array_size_to_check",
214                 mContext.getResources().getInteger(R.integer.advertise_array_size_to_check)
215         );
216         mAdvertiseArrayStartIndexToCalVariance = DeviceConfig.getInt(
217                 DeviceConfig.NAMESPACE_UWB,
218                 "advertise_array_start_index_to_cal_variance",
219                 mContext.getResources().getInteger(
220                         R.integer.advertise_array_start_index_to_cal_variance)
221         );
222         mAdvertiseArrayEndIndexToCalVariance = DeviceConfig.getInt(
223                 DeviceConfig.NAMESPACE_UWB,
224                 "advertise_array_end_index_to_cal_variance",
225                 mContext.getResources().getInteger(
226                         R.integer.advertise_array_end_index_to_cal_variance)
227         );
228         mAdvertiseTrustedVarianceValue = DeviceConfig.getInt(
229                 DeviceConfig.NAMESPACE_UWB,
230                 "advertise_trusted_variance_value",
231                 mContext.getResources().getInteger(R.integer.advertise_trusted_variance_value)
232         );
233 
234         // Rx data packets.
235         mRxDataMaxPacketsToStore = DeviceConfig.getInt(
236                 DeviceConfig.NAMESPACE_UWB,
237                 "rx_data_max_packets_to_store",
238                 mContext.getResources().getInteger(R.integer.rx_data_max_packets_to_store)
239         );
240 
241         mBackgroundRangingEnabled = DeviceConfig.getBoolean(
242                 DeviceConfig.NAMESPACE_UWB,
243                 "background_ranging_enabled",
244                 mContext.getResources().getBoolean(R.bool.background_ranging_enabled)
245         );
246 
247         mRangingErrorStreakTimerEnabled = DeviceConfig.getBoolean(
248                 DeviceConfig.NAMESPACE_UWB,
249                 "ranging_error_streak_timer_enabled",
250                 mContext.getResources().getBoolean(R.bool.ranging_error_streak_timer_enabled)
251         );
252 
253         // A little parsing and cleanup:
254         mFrontAzimuthRadiansPerSecond = (float) Math.toRadians(frontAzimuthDegreesPerSecond);
255         mBackAzimuthRadiansPerSecond = (float) Math.toRadians(backAzimuthDegreesPerSecond);
256         mMirrorScoreStdRadians = (float) Math.toRadians(mirrorScoreStdDegrees);
257         mBackNoiseInfluenceCoeff = backNoiseInfluencePercent / 100F;
258         try {
259             mPoseSourceType = PoseSourceType.valueOf(poseSourceName);
260         } catch (IllegalArgumentException e) {
261             mPoseSourceType = PoseSourceType.ROTATION_VECTOR;
262             Log.e(LOG_TAG, "UWB pose source '" + poseSourceName + "' defined in flags or"
263                     + "overlay file is invalid. Defaulting to " + mPoseSourceType.name());
264         }
265         mEnablePrimerFov = mPrimerFovDegree > 0 && mPrimerFovDegree < MAX_FOV;
266     }
267 
268     /**
269      * Gets ranging result logging interval in ms
270      */
271     public int getRangingResultLogIntervalMs() {
272         return mRangingResultLogIntervalMs;
273     }
274 
275     /**
276      * Gets the feature flag for reporting device error
277      */
278     public boolean isDeviceErrorBugreportEnabled() {
279         return mDeviceErrorBugreportEnabled;
280     }
281 
282     /**
283      * Gets the feature flag for reporting session init error
284      */
285     public boolean isSessionInitErrorBugreportEnabled() {
286         return mSessionInitErrorBugreportEnabled;
287     }
288 
289     /**
290      * Gets minimum wait time between two bug report captures
291      */
292     public int getBugReportMinIntervalMs() {
293         return mBugReportMinIntervalMs;
294     }
295 
296     /**
297      * Gets the flag for enabling UWB filtering.
298      */
299     public boolean isEnableFilters() {
300         return mEnableFilters;
301     }
302 
303     /**
304      * Gets the percentage (0-100) of inliers to be used in the distance filter cut.
305      */
306     public int getFilterDistanceInliersPercent() {
307         return mFilterDistanceInliersPercent;
308     }
309 
310     /**
311      * Gets the size of the distance filter moving window.
312      */
313     public int getFilterDistanceWindow() {
314         return mFilterDistanceWindow;
315     }
316 
317     /**
318      * Gets the percentage (0-100) of inliers to be used inthe angle filter cut.
319      */
320     public int getFilterAngleInliersPercent() {
321         return mFilterAngleInliersPercent;
322     }
323 
324     /**
325      * Gets the size of the angle filter moving window.
326      */
327     public int getFilterAngleWindow() {
328         return mFilterAngleWindow;
329     }
330 
331     /**
332      * Gets the type of pose source that should be used by default.
333      */
334     public PoseSourceType getPoseSourceType() {
335         return mPoseSourceType;
336     }
337 
338     /**
339      * Gets the flag that enables the elevation estimation primer.
340      */
341     public boolean isEnablePrimerEstElevation() {
342         return mEnablePrimerEstElevation;
343     }
344 
345     /**
346      * Gets the flag that enables the primer that converts AoA to spherical coordinates.
347      */
348     public boolean isEnablePrimerAoA() {
349         return mEnablePrimerAoA;
350     }
351 
352     /**
353      * Gets a value indicating if the FOV primer should be enabled.
354      */
355     public boolean isEnablePrimerFov() {
356         return mEnablePrimerFov;
357     }
358 
359     /**
360      * Gets the configured field of view.
361      */
362     public int getPrimerFovDegree() {
363         return mPrimerFovDegree;
364     }
365 
366     /**
367      * Gets how long to replace reports with an error status with predicted reports in seconds.
368      */
369     public int getPredictionTimeoutSeconds() {
370         return mPredictionTimeoutSeconds;
371     }
372 
373     /**
374      * Gets the flag that enables back-azimuth detection.
375      */
376     public boolean isEnableBackAzimuth() {
377         return mEnableBackAzimuth;
378     }
379 
380     /**
381      * Gets the flag that causes rear azimuth values to be replaced with predictions.
382      */
383     public boolean isEnableBackAzimuthMasking() {
384         return mEnableBackAzimuthMasking;
385     }
386 
387     /**
388      * Gets the size of the back-azimuth detection window.
389      */
390     public int getBackAzimuthWindow() {
391         return mBackAzimuthWindow;
392     }
393 
394     /**
395      * Gets minimum correlation rate required to assume azimuth readings are coming from the front.
396      */
397     public float getFrontAzimuthRadiansPerSecond() {
398         return mFrontAzimuthRadiansPerSecond;
399     }
400 
401     /**
402      * Gets minimum correlation rate required to assume azimuth readings are coming from the back.
403      */
404     public float getBackAzimuthRadiansPerSecond() {
405         return mBackAzimuthRadiansPerSecond;
406     }
407 
408     /**
409      * Gets the standard deviation of the mirror detection bell curve.
410      */
411     public float getMirrorScoreStdRadians() {
412         return mMirrorScoreStdRadians;
413     }
414 
415     /**
416      * Gets a coefficient of how much noise adds to the back-facing mirroring score.
417      */
418     public float getBackNoiseInfluenceCoeff() {
419         return mBackNoiseInfluenceCoeff;
420     }
421 
422     /**
423      * Gets the Advertising Profile AoA Criteria Angle.
424      */
425     public int getAdvertiseAoaCriteriaAngle() {
426         return mAdvertiseAoaCriteriaAngle;
427     }
428 
429     /**
430      * Gets the Advertising profile time threshold (for the received Owr Aoa Measurements).
431      */
432     public int getAdvertiseTimeThresholdMillis() {
433         return mAdvertiseTimeThresholdMillis;
434     }
435 
436     /**
437      * Gets the Advertising profile Array Size (of the stored values from Owr Aoa Measurements).
438      */
439     public int getAdvertiseArraySizeToCheck() {
440         return mAdvertiseArraySizeToCheck;
441     }
442 
443     /**
444      * Gets the Advertising profile Array Start Index (of the stored values from Owr Aoa
445      * Measurements), which we will use to calculate Variance.
446      */
447     public int getAdvertiseArrayStartIndexToCalVariance() {
448         return mAdvertiseArrayStartIndexToCalVariance;
449     }
450 
451     /**
452      * Gets the Advertising profile Array End Index (of the stored values from Owr Aoa
453      * Measurements), which we will use to calculate Variance.
454      */
455     public int getAdvertiseArrayEndIndexToCalVariance() {
456         return mAdvertiseArrayEndIndexToCalVariance;
457     }
458 
459     /**
460      * Gets the Advertising profile Trusted Variance Value (the threshold within which computed
461      * variance from the Owr Aoa Measurements is acceptable).
462      */
463     public int getAdvertiseTrustedVarianceValue() {
464         return mAdvertiseTrustedVarianceValue;
465     }
466 
467     /**
468      * Gets the max number of Rx data packets (received on a UWB session from the remote device),
469      * to be stored in the UWB framework.
470      */
471     public int getRxDataMaxPacketsToStore() {
472         return mRxDataMaxPacketsToStore;
473     }
474 
475     /**
476      * Returns whether background ranging is enabled or not.
477      * If enabled:
478      *  * Background 3p apps are allowed to open new ranging sessions
479      *  * When previously foreground 3p apps moves to background, sessions are not terminated
480      */
481     public boolean isBackgroundRangingEnabled() {
482         return mBackgroundRangingEnabled;
483     }
484 
485     /**
486      * Returns whether ranging error streak timer is enabled or not.
487      * If disabled, session would not be automatically stopped if there is no peer available.
488      */
489     public boolean isRangingErrorStreakTimerEnabled() {
490         return mRangingErrorStreakTimerEnabled;
491     }
492 }
493