/* * Copyright (C) 2012 Sony Mobile Communications AB * * This file is part of ApkAnalyser. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package andreflect.xml; import mereflect.CollaborateClassContext; import mereflect.MEClassContext; import analyser.gui.MainFrame; import andreflect.DexReferenceCache; import android.util.TypedValue; import brut.androlib.AndrolibException; import brut.androlib.res.data.ResID; import brut.androlib.res.data.ResResSpec; import brut.androlib.res.data.ResTable; import brut.androlib.res.data.value.ResReferenceValue; import brut.androlib.res.data.value.ResScalarValue; import brut.androlib.res.decoder.ResAttrDecoder; public class XmlResAttrDecoder extends ResAttrDecoder { private final ResTable mResTable; public XmlResAttrDecoder(ResTable resTable) { mResTable = resTable; } public static final int ANDROID_PACKAGE_ID = 0x1; @Override public String decode(int type, int value, String rawValue, int attrResId) { String decoded = (rawValue == null ? TypedValue.coerceToString(type, value) : rawValue); try { if (mResTable != null) { ResScalarValue resValue = mResTable.listMainPackages().iterator().next().getValueFactory().factory(type, value, rawValue); if (resValue instanceof ResReferenceValue) { decoded = getResReferenceValue((ResReferenceValue) resValue, mResTable, type == TypedValue.TYPE_ATTRIBUTE); } else { decoded = resValue.encodeAsResXmlAttr(); } } } catch (AndrolibException e1) { e1.printStackTrace(); } return decoded; } public static String getResReferenceValue(ResReferenceValue resReferenceValue, ResTable resTable, boolean isAttribute) { int id = resReferenceValue.getValue(); if (resReferenceValue.isNull()) { return "@null"; } try { if (resTable.getResSpec(id) != null) { return resReferenceValue.encodeAsResXmlAttr(); } } catch (AndrolibException e) { } CollaborateClassContext ctx = MainFrame.getInstance().getResolver().getReferenceContext(); MEClassContext[] contexts = ctx.getContexts(); for (MEClassContext context : contexts) { ResTable resFrameworkTable = null; DexReferenceCache dexResCache = context.getDexReferenceCache(); if (dexResCache != null) { resFrameworkTable = dexResCache.getResTable(); } try { if (resFrameworkTable != null && resFrameworkTable.getResSpec(id) != null) { ResReferenceValueX x = new ResReferenceValueX(resReferenceValue, resFrameworkTable); return x.encodeAsResXmlAttr(); } } catch (AndrolibException e) { //ignore because not define in this jar file } } return String.format("%s%s%08X", isAttribute ? "?" : "@", new ResID(id).package_ == ANDROID_PACKAGE_ID ? "android:" : "", resReferenceValue.getValue()); } private static class ResReferenceValueX extends ResReferenceValue { private final ResTable m_resTable; public ResReferenceValueX(ResReferenceValue resReferenceValue, ResTable resTable) { super(resReferenceValue.mPackage, resReferenceValue.getValue(), resReferenceValue.mRawValue, resReferenceValue.mTheme); m_resTable = resTable; } @Override public ResResSpec getReferent() throws AndrolibException { return m_resTable.getResSpec(getValue()); } } }