[Android Software Development] Lanchon:
on the accessor issue...

javac in java 5 introduced nested/inner classes. i say javac because this feature is all syntactic sugar added by the compiler, while the JVM definition and implementation stayed the same. one problem with java 1.0 is that it doesn't provide the much needed "friends" functionality of C++. this means that there is no way for the compiler to generate accurate access modifiers in bytecode.

this:

public class A {
static private int x;
public static class B {
public static void f() {
x = 42;
}
}
}

would compile to this:

public class A {
static private int x;
}

public class A$B {
public static void f() {
A.x = 42; // OH JEEZ! what we do now???
}
}

except there is no way to declare A$B is friends of A (able to access its private state). the java 5 team discarded:

-not allowing private access: that is chickening out of the problem!

-increasing visibility of x: that breaks encapsulation. (not source code, but binary code could access x trivially.)

java 5's solution are accessors:

public class A {
static private int x;
static synthetic int access$007(int _x) {
// accessors are package private (so the package can still be 'sealed')
// accessors are never used outside of the currently compiled class (no linkage needed)
// so accessor names cannot be predicted ('ugly' hack code cannot expect any particular name)
return (x = _x);
}
}

public class A$B {
public static void f() {
A.access$007(42); // now we talking!!!
}
}

the takeaway is java and java bytecode are different with different rules. you have to get to know a bit of bytecode to patch, unfortunately. javac 5 and later can generate a lot of synthetic methods here and there, and unfortunately these negatively impact the patching experience since you have to decide what to do with all these methods.

the rule of thumb is: avoid javac generating 'anonymous' things (classes and methods) in the patch at all cost. this is why dexpatcher fails to patch when a patch class member is untagged: to alter you to the fact that some stuff (possibly synthetic methods) are being output by javac which you didn't reason about. this was the tale-tell sign of you issue:

error: type 'com.android.server.policy.PhoneWindowManager': direct method 'access$002(com.android.server.policy.PhoneWindowManager, boolean):boolean': (PhoneWindowManager.java:16): no action defined

this means: you tried to set a non-static private boolean in PhoneWindowManager from another class in the patch.

EDIT: this is why using defaultAction=... is very strongly discouraged, and should be a last resort in cases where javac cannot be stopped from generating helper methods. i've yet to see any such instance in practice.

my source code style for this issue is documenting that i'd like the variable to be private but make it package-private, like this:

@DexAdd
/*private*/ volatile boolean volSkipPerformed;

one last warning: using volatiles is almost always an error (after java 5 and changes done to it by doug lee and friends; before java 5 it was always an error). reading/writing a volatile post java 5 is exactly as heavy as entering/exiting a monitor (has acquire/release semantics). absolutely do use monitors instead of volatiles: you have to be more clever than you think to use volatiles the right way. if you care about performance like crazy, then study and use the concurrent package (again by doug lee and friends); you cannot compete with the performance of that package with hand-crafted code.