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.server.power.stats.wakeups; 18 19 import android.annotation.XmlRes; 20 import android.content.Context; 21 import android.content.res.XmlResourceParser; 22 import android.util.ArrayMap; 23 import android.util.ArraySet; 24 import android.util.IndentingPrintWriter; 25 import android.util.LongSparseArray; 26 27 import com.android.internal.util.XmlUtils; 28 29 import org.xmlpull.v1.XmlPullParser; 30 import org.xmlpull.v1.XmlPullParserException; 31 32 import java.io.IOException; 33 import java.util.ArrayList; 34 import java.util.Collections; 35 import java.util.List; 36 37 /** 38 * Parses irq_device_map.xml to store a mapping of devices that can send IRQs to the CPU to 39 * subsystems that represent some logical work happening on the device that could need an IRQ. 40 */ 41 public class IrqDeviceMap { 42 private static final String TAG_IRQ_DEVICE_MAP = "irq-device-map"; 43 private static final String TAG_DEVICE = "device"; 44 private static final String TAG_SUBSYSTEM = "subsystem"; 45 private static final String ATTR_NAME = "name"; 46 47 private static LongSparseArray<IrqDeviceMap> sInstanceMap = new LongSparseArray<>(1); 48 49 private final ArrayMap<String, List<String>> mSubsystemsForDevice = new ArrayMap(); 50 IrqDeviceMap(XmlResourceParser parser)51 private IrqDeviceMap(XmlResourceParser parser) { 52 try { 53 XmlUtils.beginDocument(parser, TAG_IRQ_DEVICE_MAP); 54 55 int type; 56 String currentDevice = null; 57 final ArraySet<String> subsystems = new ArraySet<>(); 58 59 while ((type = parser.getEventType()) != XmlPullParser.END_DOCUMENT) { 60 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_DEVICE)) { 61 currentDevice = parser.getAttributeValue(null, ATTR_NAME); 62 } 63 if (currentDevice != null && type == XmlPullParser.END_TAG 64 && parser.getName().equals(TAG_DEVICE)) { 65 final int n = subsystems.size(); 66 if (n > 0) { 67 mSubsystemsForDevice.put(currentDevice, 68 Collections.unmodifiableList(new ArrayList<>(subsystems))); 69 } 70 subsystems.clear(); 71 currentDevice = null; 72 } 73 if (currentDevice != null && type == XmlPullParser.START_TAG 74 && parser.getName().equals(TAG_SUBSYSTEM)) { 75 parser.next(); 76 if (parser.getEventType() == XmlPullParser.TEXT) { 77 subsystems.add(parser.getText()); 78 } 79 } 80 parser.next(); 81 } 82 } catch (XmlPullParserException e) { 83 throw new RuntimeException(e); 84 } catch (IOException e) { 85 throw new RuntimeException(e); 86 } finally { 87 parser.close(); 88 } 89 } 90 91 /** 92 * Returns an instance of IrqDeviceMap initialzed with the given context and xml resource. 93 * The xml resource should describe the mapping in a way similar to 94 * core/res/res/xml/irq_device_map.xml. 95 */ getInstance(Context context, @XmlRes int resId)96 public static IrqDeviceMap getInstance(Context context, @XmlRes int resId) { 97 synchronized (IrqDeviceMap.class) { 98 final int idx = sInstanceMap.indexOfKey(resId); 99 if (idx >= 0) { 100 return sInstanceMap.valueAt(idx); 101 } 102 } 103 final XmlResourceParser parser = context.getResources().getXml(resId); 104 final IrqDeviceMap irqDeviceMap = new IrqDeviceMap(parser); 105 synchronized (IrqDeviceMap.class) { 106 sInstanceMap.put(resId, irqDeviceMap); 107 } 108 return irqDeviceMap; 109 } 110 getSubsystemsForDevice(String device)111 List<String> getSubsystemsForDevice(String device) { 112 return mSubsystemsForDevice.get(device); 113 } 114 dump(IndentingPrintWriter pw)115 void dump(IndentingPrintWriter pw) { 116 pw.println("Irq device map:"); 117 pw.increaseIndent(); 118 119 final LongSparseArray<IrqDeviceMap> instanceMap; 120 synchronized (IrqDeviceMap.class) { 121 instanceMap = sInstanceMap; 122 } 123 final int idx = instanceMap.indexOfValue(this); 124 final String res = (idx >= 0) ? ("0x" + Long.toHexString(instanceMap.keyAt(idx))) : null; 125 pw.println("Loaded from xml resource: " + res); 126 127 pw.println("Map:"); 128 pw.increaseIndent(); 129 for (int i = 0; i < mSubsystemsForDevice.size(); i++) { 130 pw.print(mSubsystemsForDevice.keyAt(i) + ": "); 131 pw.println(mSubsystemsForDevice.valueAt(i)); 132 } 133 pw.decreaseIndent(); 134 135 pw.decreaseIndent(); 136 } 137 } 138