• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.appop;
18 
19 import java.util.ArrayList;
20 import java.util.List;
21 
22 /**
23  * Helper class for migrating discrete ops from xml to sqlite
24  */
25 public class DiscreteOpsMigrationHelper {
26     /**
27      * migrate discrete ops from xml to sqlite.
28      */
migrateDiscreteOpsToSqlite(DiscreteOpsXmlRegistry xmlRegistry, DiscreteOpsSqlRegistry sqlRegistry)29     static void migrateDiscreteOpsToSqlite(DiscreteOpsXmlRegistry xmlRegistry,
30             DiscreteOpsSqlRegistry sqlRegistry) {
31         DiscreteOpsXmlRegistry.DiscreteOps xmlOps = xmlRegistry.getAllDiscreteOps();
32         List<DiscreteOpsSqlRegistry.DiscreteOp> discreteOps = getSqlDiscreteOps(xmlOps);
33         sqlRegistry.migrateXmlData(discreteOps, xmlOps.mChainIdOffset);
34         xmlRegistry.deleteDiscreteOpsDir();
35     }
36 
37     /**
38      * rollback discrete ops from sqlite to xml.
39      */
migrateDiscreteOpsToXml(DiscreteOpsSqlRegistry sqlRegistry, DiscreteOpsXmlRegistry xmlRegistry)40     static void migrateDiscreteOpsToXml(DiscreteOpsSqlRegistry sqlRegistry,
41             DiscreteOpsXmlRegistry xmlRegistry) {
42         List<DiscreteOpsSqlRegistry.DiscreteOp> sqlOps = sqlRegistry.getAllDiscreteOps();
43 
44         // Only migrate configured discrete ops. Sqlite may contain all runtime ops, and more.
45         List<DiscreteOpsSqlRegistry.DiscreteOp> filteredList = new ArrayList<>();
46         for (DiscreteOpsSqlRegistry.DiscreteOp opEvent: sqlOps) {
47             if (DiscreteOpsRegistry.isDiscreteOp(opEvent.getOpCode(), opEvent.getOpFlags())) {
48                 filteredList.add(opEvent);
49             }
50         }
51 
52         DiscreteOpsXmlRegistry.DiscreteOps xmlOps = getXmlDiscreteOps(filteredList);
53         xmlRegistry.migrateSqliteData(xmlOps);
54         sqlRegistry.deleteDatabase();
55     }
56 
57     /**
58      * Convert sqlite flat rows to hierarchical data.
59      */
getXmlDiscreteOps( List<DiscreteOpsSqlRegistry.DiscreteOp> discreteOps)60     private static DiscreteOpsXmlRegistry.DiscreteOps getXmlDiscreteOps(
61             List<DiscreteOpsSqlRegistry.DiscreteOp> discreteOps) {
62         DiscreteOpsXmlRegistry.DiscreteOps xmlOps =
63                 new DiscreteOpsXmlRegistry.DiscreteOps(0);
64         if (discreteOps.isEmpty()) {
65             return xmlOps;
66         }
67 
68         for (DiscreteOpsSqlRegistry.DiscreteOp discreteOp : discreteOps) {
69             xmlOps.addDiscreteAccess(discreteOp.getOpCode(), discreteOp.getUid(),
70                     discreteOp.getPackageName(), discreteOp.getDeviceId(),
71                     discreteOp.getAttributionTag(), discreteOp.getOpFlags(),
72                     discreteOp.getUidState(),
73                     discreteOp.getAccessTime(), discreteOp.getDuration(),
74                     discreteOp.getAttributionFlags(), (int) discreteOp.getChainId());
75         }
76         return xmlOps;
77     }
78 
79     /**
80      * Convert xml (hierarchical) data to flat row based data.
81      */
getSqlDiscreteOps( DiscreteOpsXmlRegistry.DiscreteOps discreteOps)82     private static List<DiscreteOpsSqlRegistry.DiscreteOp> getSqlDiscreteOps(
83             DiscreteOpsXmlRegistry.DiscreteOps discreteOps) {
84         List<DiscreteOpsSqlRegistry.DiscreteOp> opEvents = new ArrayList<>();
85 
86         if (discreteOps.isEmpty()) {
87             return opEvents;
88         }
89 
90         discreteOps.mUids.forEach((uid, discreteUidOps) -> {
91             discreteUidOps.mPackages.forEach((packageName, packageOps) -> {
92                 packageOps.mPackageOps.forEach((opcode, ops) -> {
93                     ops.mDeviceAttributedOps.forEach((deviceId, deviceOps) -> {
94                         deviceOps.mAttributedOps.forEach((tag, attributedOps) -> {
95                             for (DiscreteOpsXmlRegistry.DiscreteOpEvent attributedOp :
96                                     attributedOps) {
97                                 DiscreteOpsSqlRegistry.DiscreteOp
98                                         opModel = new DiscreteOpsSqlRegistry.DiscreteOp(uid,
99                                         packageName, tag,
100                                         deviceId, opcode, attributedOp.mOpFlag,
101                                         attributedOp.mAttributionFlags,
102                                         attributedOp.mUidState, attributedOp.mAttributionChainId,
103                                         attributedOp.mNoteTime,
104                                         attributedOp.mNoteDuration);
105                                 opEvents.add(opModel);
106                             }
107                         });
108                     });
109                 });
110             });
111         });
112 
113         return opEvents;
114     }
115 }
116