1 /**
2  * Copyright (C) 2023 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.rkpdapp.metrics;
18 
19 import com.android.rkpdapp.service.RemoteProvisioningService;
20 import com.android.rkpdapp.utils.StopWatch;
21 
22 /**
23  * Contains the metrics values that are recorded for every client call into RKPD.
24  * This class will automatically push an atom on close, and is intended to be used with a
25  * try-with-resources block to ensure metrics are automatically logged.
26  */
27 public final class RkpdClientOperation implements AutoCloseable {
28     private static final String TAG = RemoteProvisioningService.TAG;
29 
30     public enum Result {
31         UNKNOWN(RkpdStatsLog.RKPD_CLIENT_OPERATION__RESULT__RESULT_UNKNOWN),
32         SUCCESS(RkpdStatsLog.RKPD_CLIENT_OPERATION__RESULT__RESULT_SUCCESS),
33         CANCELED(RkpdStatsLog.RKPD_CLIENT_OPERATION__RESULT__RESULT_CANCELED),
34         RKP_UNSUPPORTED(RkpdStatsLog.RKPD_CLIENT_OPERATION__RESULT__RESULT_RKP_UNSUPPORTED),
35         ERROR_INTERNAL(RkpdStatsLog.RKPD_CLIENT_OPERATION__RESULT__RESULT_ERROR_INTERNAL),
36         ERROR_REQUIRES_SECURITY_PATCH(
37                 RkpdStatsLog
38                         .RKPD_CLIENT_OPERATION__RESULT__RESULT_ERROR_REQUIRES_SECURITY_PATCH),
39         ERROR_PENDING_INTERNET_CONNECTIVITY(
40                 RkpdStatsLog
41                         .RKPD_CLIENT_OPERATION__RESULT__RESULT_ERROR_PENDING_INTERNET_CONNECTIVITY),
42         ERROR_PERMANENT(RkpdStatsLog.RKPD_CLIENT_OPERATION__RESULT__RESULT_ERROR_PERMANENT),
43         ERROR_INVALID_HAL(RkpdStatsLog.RKPD_CLIENT_OPERATION__RESULT__RESULT_ERROR_INVALID_HAL),
44         ERROR_KEY_NOT_FOUND(RkpdStatsLog.RKPD_CLIENT_OPERATION__RESULT__RESULT_ERROR_KEY_NOT_FOUND);
45 
46         private final int mAtomValue;
47 
Result(int atomValue)48         Result(int atomValue) {
49             mAtomValue = atomValue;
50         }
51 
getAtomValue()52         public int getAtomValue() {
53             return mAtomValue;
54         }
55     }
56 
57     private final StopWatch mTimer = new StopWatch(TAG);
58     private final int mClientUid;
59     private final String mRemotelyProvisionedComponent;
60     private final int mOperationId;
61     private int mResult = RkpdStatsLog.RKPD_CLIENT_OPERATION__RESULT__RESULT_UNKNOWN;
62 
63     /** Create an object that records an atom for a getRegistration call */
getRegistration(int clientUid, String remotelyProvisionedComponent)64     public static RkpdClientOperation getRegistration(int clientUid,
65             String remotelyProvisionedComponent) {
66         return new RkpdClientOperation(clientUid, remotelyProvisionedComponent,
67                 RkpdStatsLog.RKPD_CLIENT_OPERATION__OPERATION__OPERATION_GET_REGISTRATION);
68     }
69 
70     /** Create an object that records an atom for a getKey call */
getKey(int clientUid, String remotelyProvisionedComponent)71     public static RkpdClientOperation getKey(int clientUid,
72             String remotelyProvisionedComponent) {
73         return new RkpdClientOperation(clientUid, remotelyProvisionedComponent,
74                 RkpdStatsLog.RKPD_CLIENT_OPERATION__OPERATION__OPERATION_GET_KEY);
75     }
76 
77     /** Create an object that records an atom for a cancelGetKey call */
cancelGetKey(int clientUid, String remotelyProvisionedComponent)78     public static RkpdClientOperation cancelGetKey(int clientUid,
79             String remotelyProvisionedComponent) {
80         return new RkpdClientOperation(clientUid, remotelyProvisionedComponent,
81                 RkpdStatsLog.RKPD_CLIENT_OPERATION__OPERATION__OPERATION_CANCEL_GET_KEY);
82     }
83 
84     /** Create an object that records an atom for a storeUpgradedKey call */
storeUpgradedKey(int clientUid, String remotelyProvisionedComponent)85     public static RkpdClientOperation storeUpgradedKey(int clientUid,
86             String remotelyProvisionedComponent) {
87         return new RkpdClientOperation(clientUid, remotelyProvisionedComponent,
88                 RkpdStatsLog.RKPD_CLIENT_OPERATION__OPERATION__OPERATION_STORE_UPGRADED_KEY);
89     }
90 
RkpdClientOperation(int clientUid, String remotelyProvisionedComponent, int operationId)91     private RkpdClientOperation(int clientUid, String remotelyProvisionedComponent,
92             int operationId) {
93         mClientUid = clientUid;
94         mRemotelyProvisionedComponent = remotelyProvisionedComponent;
95         mOperationId = operationId;
96         mTimer.start();
97     }
98 
setResult(Result result)99     public void setResult(Result result) {
100         mResult = result.getAtomValue();
101     }
102 
103     /** Record the atoms for this metrics object. */
104     @Override
close()105     public void close() {
106         mTimer.stop();
107         RkpdStatsLog.write(RkpdStatsLog.RKPD_CLIENT_OPERATION, mRemotelyProvisionedComponent,
108                 mClientUid, mOperationId, mResult, mTimer.getElapsedMillis());
109     }
110 }
111