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