• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.telemetry.publisher;
18 
19 import android.annotation.NonNull;
20 import android.app.StatsManager;
21 import android.app.usage.NetworkStatsManager;
22 import android.car.telemetry.TelemetryProto;
23 import android.content.Context;
24 import android.os.Handler;
25 
26 import com.android.car.CarPropertyService;
27 import com.android.car.telemetry.ResultStore;
28 import com.android.car.telemetry.UidPackageMapper;
29 import com.android.car.telemetry.publisher.net.NetworkStatsManagerProxy;
30 import com.android.car.telemetry.sessioncontroller.SessionController;
31 import com.android.internal.util.Preconditions;
32 
33 import java.util.Objects;
34 
35 /**
36  * Lazy factory class for Publishers. It's expected to have a single factory instance. Must be
37  * called from the telemetry thread.
38  *
39  * <p>It doesn't instantiate all the publishers right away, as in some cases some publishers are not
40  * needed.
41  *
42  * <p>Methods in this class must be called on telemetry thread unless specified as thread-safe.
43  */
44 public class PublisherFactory {
45     // Some publishers must be initialized as early as possible during boot.
46     private static final TelemetryProto.Publisher.PublisherCase[] sForceInitPublishers = {
47             TelemetryProto.Publisher.PublisherCase.CONNECTIVITY
48     };
49 
50     private final Object mLock = new Object();
51     private final CarPropertyService mCarPropertyService;
52     private final Handler mTelemetryHandler;
53     private final Context mContext;  // CarService context
54     private final UidPackageMapper mUidMapper;
55 
56     private VehiclePropertyPublisher mVehiclePropertyPublisher;
57     private CarTelemetrydPublisher mCarTelemetrydPublisher;
58     private StatsPublisher mStatsPublisher;
59     private ConnectivityPublisher mConnectivityPublisher;
60     private MemoryPublisher mMemoryPublisher;
61     private AbstractPublisher.PublisherListener mPublisherListener;
62     // To enable publishers to subscribe to session updates if needed.
63     private final SessionController mSessionController;
64     // To enable publishers to store pulled data in the event of suspend-to-RAM or shutdown.
65     private final ResultStore mResultStore;
66 
PublisherFactory( @onNull CarPropertyService carPropertyService, @NonNull Handler handler, @NonNull Context context, @NonNull SessionController sessionController, @NonNull ResultStore resultStore, @NonNull UidPackageMapper uidMapper)67     public PublisherFactory(
68             @NonNull CarPropertyService carPropertyService,
69             @NonNull Handler handler,
70             @NonNull Context context,
71             @NonNull SessionController sessionController,
72             @NonNull ResultStore resultStore,
73             @NonNull UidPackageMapper uidMapper) {
74         mCarPropertyService = carPropertyService;
75         mTelemetryHandler = handler;
76         mContext = context;
77         mSessionController = sessionController;
78         mResultStore = resultStore;
79         mUidMapper = uidMapper;
80     }
81 
82     /** Returns the publisher by given type. This method is thread-safe. */
83     @NonNull
getPublisher(@onNull TelemetryProto.Publisher.PublisherCase type)84     public AbstractPublisher getPublisher(@NonNull TelemetryProto.Publisher.PublisherCase type) {
85         Preconditions.checkState(mPublisherListener != null, "PublisherFactory is not initialized");
86         // No need to optimize locks, as this method is infrequently called.
87         synchronized (mLock) {
88             switch (type.getNumber()) {
89                 case TelemetryProto.Publisher.VEHICLE_PROPERTY_FIELD_NUMBER:
90                     if (mVehiclePropertyPublisher == null) {
91                         mVehiclePropertyPublisher = new VehiclePropertyPublisher(
92                                 mCarPropertyService, mPublisherListener, mTelemetryHandler);
93                     }
94                     return mVehiclePropertyPublisher;
95                 case TelemetryProto.Publisher.CARTELEMETRYD_FIELD_NUMBER:
96                     if (mCarTelemetrydPublisher == null) {
97                         mCarTelemetrydPublisher = new CarTelemetrydPublisher(
98                                 mPublisherListener, mTelemetryHandler, mSessionController);
99                     }
100                     return mCarTelemetrydPublisher;
101                 case TelemetryProto.Publisher.STATS_FIELD_NUMBER:
102                     if (mStatsPublisher == null) {
103                         StatsManager stats = mContext.getSystemService(StatsManager.class);
104                         Preconditions.checkState(stats != null, "StatsManager not found");
105                         StatsManagerProxy statsManager = new StatsManagerImpl(stats);
106                         mStatsPublisher = new StatsPublisher(
107                                 mPublisherListener, statsManager, mResultStore, mTelemetryHandler);
108                     }
109                     return mStatsPublisher;
110                 case TelemetryProto.Publisher.CONNECTIVITY_FIELD_NUMBER:
111                     if (mConnectivityPublisher == null) {
112                         NetworkStatsManager networkStatsManager =
113                                 Objects.requireNonNull(
114                                         mContext.getSystemService(NetworkStatsManager.class));
115                         mConnectivityPublisher =
116                                 new ConnectivityPublisher(
117                                         mPublisherListener,
118                                         new NetworkStatsManagerProxy(networkStatsManager),
119                                         mTelemetryHandler, mResultStore, mSessionController,
120                                         mUidMapper);
121                     }
122                     return mConnectivityPublisher;
123                 case TelemetryProto.Publisher.MEMORY_FIELD_NUMBER:
124                     if (mMemoryPublisher == null) {
125                         mMemoryPublisher = new MemoryPublisher(
126                                 mContext, mPublisherListener, mTelemetryHandler, mResultStore,
127                                 mSessionController);
128                     }
129                     return mMemoryPublisher;
130                 default:
131                     throw new IllegalArgumentException(
132                             "Publisher type " + type + " is not supported");
133             }
134         }
135     }
136 
137     /**
138      * Removes all {@link com.android.car.telemetry.databroker.DataSubscriber} from all publishers.
139      */
removeAllDataSubscribers()140     public void removeAllDataSubscribers() {
141         if (mVehiclePropertyPublisher != null) {
142             mVehiclePropertyPublisher.removeAllDataSubscribers();
143         }
144         if (mCarTelemetrydPublisher != null) {
145             mCarTelemetrydPublisher.removeAllDataSubscribers();
146         }
147         if (mStatsPublisher != null) {
148             mStatsPublisher.removeAllDataSubscribers();
149         }
150         if (mMemoryPublisher != null) {
151             mMemoryPublisher.removeAllDataSubscribers();
152         }
153     }
154 
155     /**
156      * Initializes the factory and sets the publisher listener for all the publishers.
157      * This is expected to be called before {@link #getPublisher} method. This is not the best
158      * approach, but it suits for this case.
159      */
initialize(@onNull AbstractPublisher.PublisherListener listener)160     public void initialize(@NonNull AbstractPublisher.PublisherListener listener) {
161         Preconditions.checkState(
162                 mPublisherListener == null, "PublisherFactory is already initialized");
163         mPublisherListener = listener;
164         for (TelemetryProto.Publisher.PublisherCase publisher : sForceInitPublishers) {
165             getPublisher(publisher);
166         }
167     }
168 }
169