1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker package art; 18*795d594fSAndroid Build Coastguard Worker 19*795d594fSAndroid Build Coastguard Worker import java.util.Base64; 20*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.*; 21*795d594fSAndroid Build Coastguard Worker public class Test1993 { 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Worker static class Transform { sayHi()24*795d594fSAndroid Build Coastguard Worker public void sayHi() { 25*795d594fSAndroid Build Coastguard Worker // Use lower 'h' to make sure the string will have a different string id 26*795d594fSAndroid Build Coastguard Worker // than the transformation (the transformation code is the same except 27*795d594fSAndroid Build Coastguard Worker // the actual printed String, which was making the test inacurately passing 28*795d594fSAndroid Build Coastguard Worker // in JIT mode when loading the string from the dex cache, as the string ids 29*795d594fSAndroid Build Coastguard Worker // of the two different strings were the same). 30*795d594fSAndroid Build Coastguard Worker // We know the string ids will be different because lexicographically: 31*795d594fSAndroid Build Coastguard Worker // "Goodbye" < "LTransform;" < "hello". 32*795d594fSAndroid Build Coastguard Worker System.out.println("hello"); 33*795d594fSAndroid Build Coastguard Worker } 34*795d594fSAndroid Build Coastguard Worker } 35*795d594fSAndroid Build Coastguard Worker 36*795d594fSAndroid Build Coastguard Worker /** 37*795d594fSAndroid Build Coastguard Worker * base64 encoded class/dex file for 38*795d594fSAndroid Build Coastguard Worker * class Transform { 39*795d594fSAndroid Build Coastguard Worker * public void sayHi() { 40*795d594fSAndroid Build Coastguard Worker * System.out.println("Goodbye"); 41*795d594fSAndroid Build Coastguard Worker * } 42*795d594fSAndroid Build Coastguard Worker * } 43*795d594fSAndroid Build Coastguard Worker */ 44*795d594fSAndroid Build Coastguard Worker private static final byte[] DEX_BYTES = Base64.getDecoder().decode( 45*795d594fSAndroid Build Coastguard Worker "ZGV4CjAzNQDxrdbiBcsn0r58mdtcdyDxVUxwbWfShNQwBAAAcAAAAHhWNBIAAAAAAAAAAGwDAAAV" + 46*795d594fSAndroid Build Coastguard Worker "AAAAcAAAAAkAAADEAAAAAgAAAOgAAAABAAAAAAEAAAQAAAAIAQAAAQAAACgBAADoAgAASAEAAJIB" + 47*795d594fSAndroid Build Coastguard Worker "AACaAQAAowEAAL0BAADNAQAA8QEAABECAAAoAgAAPAIAAFACAABkAgAAcwIAAH4CAACBAgAAhQIA" + 48*795d594fSAndroid Build Coastguard Worker "AJICAACYAgAAnQIAAKYCAACtAgAAtAIAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAA" + 49*795d594fSAndroid Build Coastguard Worker "DAAAAAwAAAAIAAAAAAAAAA0AAAAIAAAAjAEAAAcABAAQAAAAAAAAAAAAAAAAAAAAEgAAAAQAAQAR" + 50*795d594fSAndroid Build Coastguard Worker "AAAABQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAACgAAAFwDAAA7AwAAAAAAAAEAAQABAAAAgAEAAAQA" + 51*795d594fSAndroid Build Coastguard Worker "AABwEAMAAAAOAAMAAQACAAAAhAEAAAgAAABiAAAAGgEBAG4gAgAQAA4AAwAOAAUADngAAAAAAQAA" + 52*795d594fSAndroid Build Coastguard Worker "AAYABjxpbml0PgAHR29vZGJ5ZQAYTGFydC9UZXN0MTk5MyRUcmFuc2Zvcm07AA5MYXJ0L1Rlc3Qx" + 53*795d594fSAndroid Build Coastguard Worker "OTkzOwAiTGRhbHZpay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0" + 54*795d594fSAndroid Build Coastguard Worker "aW9uL0lubmVyQ2xhc3M7ABVMamF2YS9pby9QcmludFN0cmVhbTsAEkxqYXZhL2xhbmcvT2JqZWN0" + 55*795d594fSAndroid Build Coastguard Worker "OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2YS9sYW5nL1N5c3RlbTsADVRlc3QxOTkzLmphdmEA" + 56*795d594fSAndroid Build Coastguard Worker "CVRyYW5zZm9ybQABVgACVkwAC2FjY2Vzc0ZsYWdzAARuYW1lAANvdXQAB3ByaW50bG4ABXNheUhp" + 57*795d594fSAndroid Build Coastguard Worker "AAV2YWx1ZQB2fn5EOHsiY29tcGlsYXRpb24tbW9kZSI6ImRlYnVnIiwibWluLWFwaSI6MSwic2hh" + 58*795d594fSAndroid Build Coastguard Worker "LTEiOiJjZDkwMDIzOTMwZDk3M2Y1NzcxMWYxZDRmZGFhZDdhM2U0NzE0NjM3IiwidmVyc2lvbiI6" + 59*795d594fSAndroid Build Coastguard Worker "IjEuNy4xNC1kZXYifQACAgETGAECAwIOBAgPFwsAAAEBAICABMgCAQHgAgAAAAAAAAACAAAALAMA" + 60*795d594fSAndroid Build Coastguard Worker "ADIDAABQAwAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAAAAAAEAAAAVAAAAcAAAAAIAAAAJAAAA" + 61*795d594fSAndroid Build Coastguard Worker "xAAAAAMAAAACAAAA6AAAAAQAAAABAAAAAAEAAAUAAAAEAAAACAEAAAYAAAABAAAAKAEAAAEgAAAC" + 62*795d594fSAndroid Build Coastguard Worker "AAAASAEAAAMgAAACAAAAgAEAAAEQAAABAAAAjAEAAAIgAAAVAAAAkgEAAAQgAAACAAAALAMAAAAg" + 63*795d594fSAndroid Build Coastguard Worker "AAABAAAAOwMAAAMQAAACAAAATAMAAAYgAAABAAAAXAMAAAAQAAABAAAAbAMAAA=="); 64*795d594fSAndroid Build Coastguard Worker run()65*795d594fSAndroid Build Coastguard Worker public static void run() throws Exception { 66*795d594fSAndroid Build Coastguard Worker Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE); 67*795d594fSAndroid Build Coastguard Worker doTest(new Transform()); 68*795d594fSAndroid Build Coastguard Worker } 69*795d594fSAndroid Build Coastguard Worker doTest(Transform t)70*795d594fSAndroid Build Coastguard Worker public static void doTest(Transform t) throws Exception { 71*795d594fSAndroid Build Coastguard Worker System.out.println("Can structurally Redefine: " + 72*795d594fSAndroid Build Coastguard Worker Redefinition.isStructurallyModifiable(Transform.class)); 73*795d594fSAndroid Build Coastguard Worker t.sayHi(); 74*795d594fSAndroid Build Coastguard Worker Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); 75*795d594fSAndroid Build Coastguard Worker t.sayHi(); 76*795d594fSAndroid Build Coastguard Worker // Check and make sure we didn't structurally redefine by looking for ClassExt.obsoleteClass 77*795d594fSAndroid Build Coastguard Worker Field ext_data_field = Class.class.getDeclaredField("extData"); 78*795d594fSAndroid Build Coastguard Worker ext_data_field.setAccessible(true); 79*795d594fSAndroid Build Coastguard Worker Object ext_data = ext_data_field.get(Transform.class); 80*795d594fSAndroid Build Coastguard Worker Field obsolete_class_field = ext_data.getClass().getDeclaredField("obsoleteClass"); 81*795d594fSAndroid Build Coastguard Worker obsolete_class_field.setAccessible(true); 82*795d594fSAndroid Build Coastguard Worker if (obsolete_class_field.get(ext_data) != null) { 83*795d594fSAndroid Build Coastguard Worker System.out.println("Expected no ClassExt.obsoleteClass but got " + obsolete_class_field.get(ext_data)); 84*795d594fSAndroid Build Coastguard Worker } 85*795d594fSAndroid Build Coastguard Worker } 86*795d594fSAndroid Build Coastguard Worker } 87