SDK source 를 보다가 bit 연산에서 막히시는 분들이 있을 것 같아 설명을 올립니다.

일반적으로 bit 연산은 Code 가독성에 있어서 단점으로 지적되기 때문에 잘 사용을 안하긴 하지만,
Mobile 이라는 특성과 비교적 자주 사용되는 다중 Flag 처리와 비교 연산 및 값 판별에서는 SDK 에서도 bit 연산을 하고 있습니다.

대표적으로 View 의 public void draw(Canvas canvas) 와 같은 경우가 있습니다.

- 다중 Flag 처리
보통 다중 Flag 의 상수값은 각 bit 의 값이 중복되지 않도록 1, 2^x (x=1,2,3,4) 값을 사용합니다.
FLAG1 = 0001
FLAG2 = 0010
FLAG4 = 0100
FLAG8 = 1000
와 같이 각 bit 값이 중복되지 않도록 하는게 중요합니다.
각 Flag 의 on 은 해당 bit 값을 1 로 하고, off 는 해당 bit 값을 0 으로 하여 판단합니다.
위 Flag 들을 예를 들면 FLAG1 과 FLAG2 가 on 되어 있는 상태값은 0011 이 되며,
이는 | (or) 연산으로 처리됩니다. (FLAG1 | FLAG2 = 0011)
또한, 어떤 값에서 해당 Flag 를 off 시키는 경우는 해당 Flag 의 보수를 & (and) 연산하여 처리할 수 있습니다.
예를 들어 FLAG2 의 보수 ~FLAG2 는 1101 이며 0011 & 1101 = 0001 이 되어 FLAG2 가 off 되게 됩니다.

View 의 public void draw(Canvas canvas) 를 보면 아래와 같은 구문이 있습니다.
final boolean dirtyOpaque =
  (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE
  && (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);

여기서 상수는,
static final int DIRTY = 0x00200000;
static final int DIRTY_OPAQUE = 0x00400000;
static final int DIRTY_MASK = 0x00600000;
으로 정의가 되어 있는데요.

이를 이진수로 바꿔보면...
DIRTY = ...0010...
DIRTY_OPAQUE = ...0100...
DIRTY_MASK = ...0110...
으로 DIRTY_MASK = DIRTY_OPAQUE | DIRTY 로 or 연산을 했다는 걸 알 수 있습니다.

여기서 (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE 부분을 생각해 보면,
privateFlags 변수와 DIRTY_MASK 를 and 연산한 경우 나올 수 있는 값은,
DIRTY 만 on 상태인 경우(...0010...),
DIRTY_OPAQUE 만 on 상태인 경우 (...0100...),
DIRTY 와 DIRTY_OPAQUE 둘다 on 상태인 경우(...0110...),
DIRTY 와 DIRTY_OPAQUE 둘다 off 상태인 경우(...0000...)
이렇게 네가지 경우가 있습니다.
이 네가지 경우에서 == DIRTY_OPAQUE 로 연산했다는 것은,
DIRTY_OPAQUE 만 on 상태인지 여부를 알고자 했다는 걸 알 수 있습니다.

만약, privateFlags 에 DIRTY 의 on/off 에 상관 없이 DIRTY_OPAQUE 가 on 상태인지 여부를 알고자 했다면,
(privateFlags & DIRTY_OPAQUE) == DIRTY_OPAQUE 와 같이 사용됩니다.

- 비교연산
보통 (A==0 && B== 0) 과 같은 비교 문장을 쓸 때도 bit 연산이 활용됩니다.
A 와 B 둘다 0 이 아닌 경우 A | B 는 어떤 경우라도 0 이 될 수 없습니다.
즉, (A==0 && B== 0) 은 ((A | B) == 0) 과 같습니다.
또한, (A!=0 || B!= 0) 은 ((A | B) != 0) 과 같습니다.

이 부분은 View 의 public void draw(Canvas canvas) 에 아래와 같이 사용되는 걸 확인할 수 있습니다.
if ((scrollX | scrollY) == 0) { ... }

- 값 판별
A 란 값을 조건 B 의 true / false 여부에 따라 A 값을 그대로 사용하거나 0 을 사용하거나 하는 경우가 있습니다.
이럴 때도 Bit 연산이 활용됩니다.

View 의 protected final void onDrawScrollBars(Canvas canvas) 부분을 보면,
...
final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
...
top = scrollY + height - size - (mUserPaddingBottom & inside);
...
과 같이 사용되는 부분이 있습니다.

해석해 보면,
viewFlags 에 SCROLLBARS_OUTSIDE_MASK 에 해당하는 값들이 있는지 판별한 후
값들이 없으면 0 의 보수를, 값들이 있으면 0 을 inside 변수에 저장합니다.
그후 (mUserPaddingBottom & inside) 를 통해
inside 값이 0 의 보수인 경우, 즉  SCROLLBARS_OUTSIDE_MASK 에 해당하지 않는 경우
mUserPaddingBottom 이 그대로 사용되고,
inside 값이 0 인 경우, 즉  SCROLLBARS_OUTSIDE_MASK 에 해당하는 경우
mUserPaddingBottom 대신에 0 을 사용하는 구조로 이루어져 있는 걸 알 수 있습니다.


감사합니다.
FLOO ( http://floo.co.kr/ )