<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://nivkhdif.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://nivkhdif.github.io/" rel="alternate" type="text/html" /><updated>2020-09-09T11:58:46+00:00</updated><id>https://nivkhdif.github.io/feed.xml</id><title type="html">AOSP FRAMEWORK</title><subtitle></subtitle><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><entry><title type="html">스레드관련</title><link href="https://nivkhdif.github.io/2020-09-09/1" rel="alternate" type="text/html" title="스레드관련" /><published>2020-09-09T00:00:00+00:00</published><updated>2020-09-09T00:00:00+00:00</updated><id>https://nivkhdif.github.io/2020-09-09/1</id><content type="html" xml:base="https://nivkhdif.github.io/2020-09-09/1">&lt;h2 id=&quot;스레드-구조&quot;&gt;스레드 구조&lt;/h2&gt;

&lt;p&gt;스레드 - 루퍼 - 핸들러&lt;/p&gt;

&lt;p&gt;루퍼와 핸들러로 스레드간의 통신을 한다.&lt;/p&gt;

&lt;p&gt;핸들러는 요청을 받아서 큐에넣는다.&lt;/p&gt;

&lt;p&gt;루퍼는 큐에서 하나씩 뽑아서&lt;/p&gt;

&lt;p&gt;핸들러에게 처리하라고 던져준다&lt;/p&gt;

&lt;p&gt;다른스레드 » 핸들러로요청 » 루퍼의QUQUE »핸들러로전달 » 처리&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\9e902d19aff119ebb6c9b91fdfe5ea3d.png&quot; alt=&quot;9e902d19aff119ebb6c9b91fdfe5ea3d.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;스레드는 하나의 Looper를 가지며&lt;/p&gt;

&lt;p&gt;Looper는 하나의 message queue를가짐&lt;/p&gt;

&lt;p&gt;스레드에서 looper, handler를 생성할때 둘을 연결함&lt;/p&gt;

&lt;h1 id=&quot;스레드종류&quot;&gt;스레드종류&lt;/h1&gt;

&lt;p&gt;HandlerThread exends thread         «.start를 호출해서 스레드 생성, looper와 handler를 멤버로가짐&lt;/p&gt;

&lt;p&gt;Servicethread extends handlerthread       « 서비스 스레드 종료되면 안되는것들&lt;/p&gt;

&lt;h2 id=&quot;ui스레드&quot;&gt;UI스레드&lt;/h2&gt;

&lt;p&gt;모든 UI관련 처리를 하는 singleton 스레드&lt;/p&gt;

&lt;p&gt;ui에서 지연이 생기면 상호작용이 멈추기때문에&lt;/p&gt;

&lt;p&gt;ui스레드 이외엔 ui에 접근할수없게해놓음&lt;/p&gt;

&lt;h2 id=&quot;메인스레드-ui스레드&quot;&gt;메인스레드 (UI스레드)&lt;/h2&gt;

&lt;p&gt;frameworks/base/core/java/android/app/ActivityThread.java&lt;/p&gt;

&lt;p&gt;activitythread.java 클래스이며&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\88f15be361e592cf20234b8b5aad5e5c.png&quot; alt=&quot;88f15be361e592cf20234b8b5aad5e5c.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;public static void main(string[] args)&lt;/p&gt;

&lt;p&gt;메인함수가있음&lt;/p&gt;

&lt;p&gt;앱이 시작될때 생성되며,&lt;/p&gt;

&lt;p&gt;사용자에게 보여지는 UI 접근, 업데이트를 UI스레드에 요청.&lt;/p&gt;

&lt;p&gt;컴포넌트(액티비티, 서비스, 브로드캐스트 리시버, Application) 처리를담당.&lt;/p&gt;

&lt;h2 id=&quot;다른스레드-클래스들&quot;&gt;다른스레드 클래스들&lt;/h2&gt;

&lt;p&gt;Displaythread  화면관리 스레드 ,&lt;/p&gt;

&lt;p&gt;이 스레드를 사용하는 클래스는  displaymanager, inputmanager , windowmanager 뿐임&lt;/p&gt;

&lt;p&gt;Connectivitythread :: 네트워크 관련&lt;/p&gt;

&lt;p&gt;Backgroundtheread :: 백그라운드 태스크관련&lt;/p&gt;

&lt;p&gt;surfaceview :: view 자체가 스레드인 view&lt;/p&gt;

&lt;h2 id=&quot;동기화&quot;&gt;동기화&lt;/h2&gt;

&lt;p&gt;구현 메서드가 여러 스레드로부터 접근되는경우&lt;/p&gt;

&lt;p&gt;주로 원격호출에서 발생&lt;/p&gt;

&lt;p&gt;ibinder호출이 binder와 동일한 프로세스이면 호출자의 스레드에서 실행&lt;/p&gt;

&lt;p&gt;만약 다른프로세스로부터의 호출이면 다른프로세스의 호출도 현재 스레드에서 실행됨&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">스레드 구조</summary></entry><entry><title type="html">동기화 자료구조 테스트2</title><link href="https://nivkhdif.github.io/2020-09-02/1" rel="alternate" type="text/html" title="동기화 자료구조 테스트2" /><published>2020-09-02T00:00:00+00:00</published><updated>2020-09-02T00:00:00+00:00</updated><id>https://nivkhdif.github.io/2020-09-02/1</id><content type="html" xml:base="https://nivkhdif.github.io/2020-09-02/1">&lt;p&gt;스레드 4개를 생성후&lt;/p&gt;

&lt;p&gt;자료구조를 바꿔가며 정수 10000개를 add,get&lt;/p&gt;

&lt;p&gt;각 스레드들이 연산을 하는데 걸리는시간과&lt;/p&gt;

&lt;p&gt;모든스레드가 작업을 완수할때까지의 시간을측정&lt;/p&gt;

&lt;p&gt;여러번 실행해서 제일 평균에 가까운값&lt;/p&gt;

&lt;h3 id=&quot;1일반-arraylist&quot;&gt;1.일반 arraylist&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;..\assets\52b838faf7bc66974a50175790a574f1.png&quot; alt=&quot;52b838faf7bc66974a50175790a574f1.png&quot; /&gt;
&lt;img src=&quot;..\assets\d9ec13d58cf32e0800344ec1b587feb7.png&quot; alt=&quot;d9ec13d58cf32e0800344ec1b587feb7.png&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;2arraylist-동기화블럭&quot;&gt;2.arraylist 동기화블럭&lt;/h3&gt;

&lt;p&gt;add를 부르는 method를 동기화처리.&lt;/p&gt;

&lt;p&gt;–현재 안드로이드에서 보이는코드&lt;/p&gt;

&lt;p&gt;–collection.synchronizedarraylist 는 read작업에도 lock이 걸려서 안쓰는듯함&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\adbea1d45f1f4581aa2fb4b447c1328b.png&quot; alt=&quot;adbea1d45f1f4581aa2fb4b447c1328b.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;read는 동기화를 걸지않아서 1번 결과와 다를게없음.&lt;/p&gt;

&lt;p&gt;대신에 size를 매번 연산해보기로함&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\842fa1ec4f7e51ad171bf161333e0388.png&quot; alt=&quot;842fa1ec4f7e51ad171bf161333e0388.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;10000개의 원소인데 성능차이가 그렇게 많이안남&lt;/p&gt;

&lt;h3 id=&quot;3copyonarraylist&quot;&gt;3.copyonarraylist&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\19cdf900681bbea3f37e0eaf086bb005.png&quot; alt=&quot;19cdf900681bbea3f37e0eaf086bb005.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\0f00e6e69659882c775ff2ec81704041.png&quot; alt=&quot;0f00e6e69659882c775ff2ec81704041.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;쓰기는 매우느리고&lt;/p&gt;

&lt;p&gt;읽기는 멀티스레드 환경에서는 확실히 이점이있음&lt;/p&gt;

&lt;p&gt;2번이 일반적인 상황에서 제일 합리적으로보임&lt;/p&gt;

&lt;p&gt;copyonarraylist 를 사용하려면 데이터의 갯수가 적지않고&lt;/p&gt;

&lt;p&gt;읽기가 많고 매우 정적인 데이터와 관련된 배열을 찾아야 장점을 살릴수있을듯함&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">스레드 4개를 생성후</summary></entry><entry><title type="html">copyonarraylist 테스트</title><link href="https://nivkhdif.github.io/2020-08-26/a" rel="alternate" type="text/html" title="copyonarraylist 테스트" /><published>2020-08-26T00:00:00+00:00</published><updated>2020-08-26T00:00:00+00:00</updated><id>https://nivkhdif.github.io/2020-08-26/a</id><content type="html" xml:base="https://nivkhdif.github.io/2020-08-26/a">&lt;p&gt;각각 자료구조 생성후 정수 10000개를&lt;/p&gt;

&lt;p&gt;add , get 하는데 걸리는 시간측정&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\5a5c86bf808133310ab2843ea9cfb45d.png&quot; alt=&quot;5a5c86bf808133310ab2843ea9cfb45d.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이런 모양으로 자료구조만 바꾸어서 테스트 해보았습니다&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\298f54e9c4d29f62569633b26181ab48.png&quot; alt=&quot;298f54e9c4d29f62569633b26181ab48.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;매번 오락가락 하지만 대체적으로 읽는 효율이 괜찮고&lt;/p&gt;

&lt;p&gt;쓰는효율은 좀 심각합니다&lt;/p&gt;

&lt;p&gt;멀티스레드 환경이라면 더 이득이 있을거같지만&lt;/p&gt;

&lt;p&gt;쓰기 성능이 너무 느려서 잃는게 더 많을거같아보입니다&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">각각 자료구조 생성후 정수 10000개를</summary></entry><entry><title type="html">화면 회전</title><link href="https://nivkhdif.github.io/2020-08-12/1" rel="alternate" type="text/html" title="화면 회전" /><published>2020-08-12T00:00:00+00:00</published><updated>2020-08-12T00:00:00+00:00</updated><id>https://nivkhdif.github.io/2020-08-12/1</id><content type="html" xml:base="https://nivkhdif.github.io/2020-08-12/1">&lt;h3 id=&quot;화면-회전시-컨텐츠-변경방법-조사&quot;&gt;화면 회전시 컨텐츠 변경방법 조사&lt;/h3&gt;

&lt;p&gt;앱개발자는 개발시에 xml에  landscape, portrait 2가지 버젼의 app layout을&lt;/p&gt;

&lt;p&gt;미리 작성해두어야한다.&lt;/p&gt;

&lt;p&gt;그리고 화면구성이 바뀔시에 다른 버젼의 xml로 변경함으로써 회전을핸들.&lt;/p&gt;

&lt;h3 id=&quot;회전시-실제-일어나는-일과-느린이유&quot;&gt;회전시 실제 일어나는 일과 느린이유?&lt;/h3&gt;

&lt;p&gt;https://developer.android.com/guide/topics/resources/runtime-changes 에 따르면,&lt;/p&gt;

&lt;p&gt;안드로이드는 기본적으로 configuration class에서 회전을 포함한&lt;/p&gt;

&lt;p&gt;그 어떤 멤버라도 변화가 생기면 view만 새로 가져오는게아니라&lt;/p&gt;

&lt;p&gt;activity 자체를 완전히 destory한후  다시 start, resume 을 거친다&lt;/p&gt;

&lt;p&gt;즉 회전할때마다 사실상 프로세스를 재시작 시키며.&lt;/p&gt;

&lt;p&gt;재시작전에 기존의 데이터들을 save 하고 재시작후 restore한다.&lt;/p&gt;

&lt;p&gt;이렇게 하는이유는 이것이 변경처리 오류 가능성을 줄이기 떄문이라고한다.&lt;/p&gt;

&lt;p&gt;하지만 단점도 있는데 문서의 내용에 따르면,&lt;/p&gt;

&lt;p&gt;기존데이터가 복잡하거나, activity에 network, background task가 걸려있으면&lt;/p&gt;

&lt;p&gt;그 저장,복구가 오래걸리며, 데이터 손실의 가능성도 있다고한다.&lt;/p&gt;

&lt;p&gt;? 아이폰은 액티비티의 재시작없이 처리한다고함.&lt;/p&gt;

&lt;h3 id=&quot;해결책&quot;&gt;해결책?&lt;/h3&gt;

&lt;p&gt;이런 재시작을 막을 방법을 2가지를 제시해줬는데&lt;/p&gt;

&lt;p&gt;하나는 재시작을 제한을 미리 선언하는것이다.&lt;/p&gt;

&lt;p&gt;그런데 이렇게하면 개발자가 직접 모든 구성변경시 발생가능한 예외를 모조리 직접처리해야하고&lt;/p&gt;

&lt;p&gt;하나라도 빼먹으면 회전이 적용되지 않는다고함. 구글은 추천하지않음&lt;/p&gt;

&lt;p&gt;둘째는 view model로 재시작은 하지만 데이터를 view 자체에 저장하는 view class인&lt;/p&gt;

&lt;p&gt;viewmodel을 이용해서 데이터 저장 - 복구의 오버헤드를 줄이는 방법이다.&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">화면 회전시 컨텐츠 변경방법 조사</summary></entry><entry><title type="html">화면 회전 관련내용</title><link href="https://nivkhdif.github.io/2020-08-05/1" rel="alternate" type="text/html" title="화면 회전 관련내용" /><published>2020-08-05T00:00:00+00:00</published><updated>2020-08-05T00:00:00+00:00</updated><id>https://nivkhdif.github.io/2020-08-05/1</id><content type="html" xml:base="https://nivkhdif.github.io/2020-08-05/1">&lt;p&gt;평소에 폰을 사용할때 디스플레이의 방향전환, 회전이 발생할때&lt;/p&gt;

&lt;p&gt;뭔가 반응이 느리고 멈추는일이 잦은거같아서 찾아보았습니다&lt;/p&gt;

&lt;p&gt;(센서감지callback  or  앱 – 프레임워크 메소드호출)&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;p&gt;public void setRequestedOrientation(@ActivityInfo.ScreenOrientation int requestedOrientation) {&lt;/p&gt;

&lt;p&gt;5759        if (mParent == null) {&lt;/p&gt;

&lt;p&gt;5760            try {&lt;/p&gt;

&lt;p&gt;5761                ActivityManager.getService().setRequestedOrientation(&lt;/p&gt;

&lt;p&gt;5762                        mToken, requestedOrientation);&lt;/p&gt;

&lt;p&gt;5763            } catch (RemoteException e) {&lt;/p&gt;

&lt;p&gt;5764                // Empty&lt;/p&gt;

&lt;p&gt;5765            }&lt;/p&gt;

&lt;p&gt;5766        } else {&lt;/p&gt;

&lt;p&gt;5767            mParent.setRequestedOrientation(requestedOrientation);&lt;/p&gt;

&lt;p&gt;5768        }&lt;/p&gt;

&lt;p&gt;5769    }
`
액티비티 매니저의 setrequested orientation 호출&lt;/p&gt;

&lt;p&gt;그후에  activityrecord 의 setRequestedOrientation 호출&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;p&gt;2193    void setRequestedOrientation(int requestedOrientation) {&lt;/p&gt;

&lt;p&gt;2194        final int displayId = getDisplayId();&lt;/p&gt;

&lt;p&gt;2195        final Configuration displayConfig =&lt;/p&gt;

&lt;p&gt;2196                mStackSupervisor.getDisplayOverrideConfiguration(displayId);&lt;/p&gt;

&lt;p&gt;2197&lt;/p&gt;

&lt;p&gt;2198        final Configuration config = mWindowContainerController.setOrientation(requestedOrientation,&lt;/p&gt;

&lt;p&gt;2199                displayId, displayConfig, mayFreezeScreenLocked(app));&lt;/p&gt;

&lt;p&gt;2200        if (config != null) {&lt;/p&gt;

&lt;p&gt;2201            frozenBeforeDestroy = true;&lt;/p&gt;

&lt;p&gt;2202            if (!service.updateDisplayOverrideConfigurationLocked(config, this,&lt;/p&gt;

&lt;p&gt;2203                    false /* deferResume */, displayId)) {&lt;/p&gt;

&lt;p&gt;2204                mStackSupervisor.resumeFocusedStackTopActivityLocked();&lt;/p&gt;

&lt;p&gt;2205            }&lt;/p&gt;

&lt;p&gt;2206        }&lt;/p&gt;

&lt;p&gt;2207        service.mTaskChangeNotificationController.notifyActivityRequestedOrientationChanged(&lt;/p&gt;

&lt;p&gt;2208                task.taskId, requestedOrientation);&lt;/p&gt;

&lt;p&gt;2209    }&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;p&gt;여기서 display (출력 device) 의 config를 변경한후에&lt;/p&gt;

&lt;p&gt;config를 적용하도록 하는듯 보입니다.&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;p&gt;275    public Configuration setOrientation(int requestedOrientation, int displayId,&lt;/p&gt;

&lt;p&gt;276            Configuration displayConfig, boolean freezeScreenIfNeeded) {&lt;/p&gt;

&lt;p&gt;277        synchronized(mWindowMap) {&lt;/p&gt;

&lt;p&gt;278            if (mContainer == null) {&lt;/p&gt;

&lt;p&gt;279                Slog.w(TAG_WM,&lt;/p&gt;

&lt;p&gt;280                        “Attempted to set orientation of non-existing app token: “ + mToken);&lt;/p&gt;

&lt;p&gt;281                return null;&lt;/p&gt;

&lt;p&gt;282            }&lt;/p&gt;

&lt;p&gt;283&lt;/p&gt;

&lt;p&gt;284            mContainer.setOrientation(requestedOrientation);&lt;/p&gt;

&lt;p&gt;285&lt;/p&gt;

&lt;p&gt;286            final IBinder binder = freezeScreenIfNeeded ? mToken.asBinder() : null;&lt;/p&gt;

&lt;p&gt;287            return mService.updateOrientationFromAppTokens(displayConfig, binder, displayId);&lt;/p&gt;

&lt;p&gt;288&lt;/p&gt;

&lt;p&gt;289        }&lt;/p&gt;

&lt;p&gt;290    }&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;p&gt;윈도우 매니저 서비스 디렉토리에있는&lt;/p&gt;

&lt;p&gt;AppWindowContainerController.java 에서..&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;p&gt;2574    boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {&lt;/p&gt;

&lt;p&gt;2575        long ident = Binder.clearCallingIdentity();&lt;/p&gt;

&lt;p&gt;2576        try {&lt;/p&gt;

&lt;p&gt;2577            final DisplayContent dc = mRoot.getDisplayContent(displayId);&lt;/p&gt;

&lt;p&gt;2578            final int req = dc.getOrientation();&lt;/p&gt;

&lt;p&gt;2579            if (req != dc.getLastOrientation()) {&lt;/p&gt;

&lt;p&gt;2580                dc.setLastOrientation(req);&lt;/p&gt;

&lt;p&gt;2581                //send a message to Policy indicating orientation change to take&lt;/p&gt;

&lt;p&gt;2582                //action like disabling/enabling sensors etc.,&lt;/p&gt;

&lt;p&gt;2583                // TODO(multi-display): Implement policy for secondary displays.&lt;/p&gt;

&lt;p&gt;2584                if (dc.isDefaultDisplay) {&lt;/p&gt;

&lt;p&gt;2585                    mPolicy.setCurrentOrientationLw(req);&lt;/p&gt;

&lt;p&gt;2586                }&lt;/p&gt;

&lt;p&gt;2587                if (dc.updateRotationUnchecked(inTransaction)) {&lt;/p&gt;

&lt;p&gt;2588                    // changed&lt;/p&gt;

&lt;p&gt;2589                    return true;&lt;/p&gt;

&lt;p&gt;2590                }&lt;/p&gt;

&lt;p&gt;2591            }&lt;/p&gt;

&lt;p&gt;2592&lt;/p&gt;

&lt;p&gt;2593            return false;&lt;/p&gt;

&lt;p&gt;2594        } finally {&lt;/p&gt;

&lt;p&gt;2595            Binder.restoreCallingIdentity(ident);&lt;/p&gt;

&lt;p&gt;2596        }&lt;/p&gt;

&lt;p&gt;2597&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;p&gt;윈도우매니저 서비스에서…&lt;/p&gt;

&lt;p&gt;뒤에도 같은 클래스내의 함수인데 lock이 걸린함수를 부르는걸로보아&lt;/p&gt;

&lt;p&gt;완전히 회전이 완료되기전까지 앱을 freeze 하는듯 보입니다.&lt;/p&gt;

&lt;p&gt;이런 멈춤을 최소화하려면 회전된 비트맵을 빨리 그려야할거같습니다.&lt;/p&gt;

&lt;p&gt;혹은중간 과정을 줄여야 할거같습니다.&lt;/p&gt;

&lt;p&gt;ㅡㅡ아이디어?&lt;/p&gt;

&lt;p&gt;만약 기존 비트맵처럼 그린다면..&lt;/p&gt;

&lt;p&gt;1.코드의 비트맵을 그릴떄,&lt;/p&gt;

&lt;p&gt;2.회전상태,  반전상태에 따라서 if 문을 사용함&lt;/p&gt;

&lt;p&gt;3.그리고 getpixel,setpixel 의 메소드를 사용해서 오버헤드가 걸림&lt;/p&gt;

&lt;p&gt;회전4가지 상태에 그 반전으로 8가지이고&lt;/p&gt;

&lt;p&gt;역행렬,좌우반전,상하반전 이렇게 3가지를 flag로 두면&lt;/p&gt;

&lt;p&gt;if문 없이도 8가지 상태를 표현할수 있을거같았음.&lt;/p&gt;

&lt;p&gt;if문의 오버헤드를 줄이고,&lt;/p&gt;

&lt;p&gt;90도의 rotation과&lt;/p&gt;

&lt;p&gt;vertical, horizontal flip ,&lt;/p&gt;

&lt;p&gt;transpose&lt;/p&gt;

&lt;p&gt;관련된 함수를 하나로 합칠수있을것으로보임.&lt;/p&gt;

&lt;p&gt;+getpixel, setpixel 함수호출의 오버헤드를 없앨수있음&lt;/p&gt;

&lt;p&gt;이 호출은 확실히 성능에 안좋다.&lt;/p&gt;

&lt;p&gt;단점:&lt;/p&gt;

&lt;p&gt;빨라질지의문 =(if문의 오버헤드 가  true false boolean혹은 bit 연산의 오버헤드보다 큰게맞는가?)&lt;/p&gt;

&lt;p&gt;코드를 알아보기 힘들어짐.&lt;/p&gt;

&lt;p&gt;만약에 식을 이렇게&lt;/p&gt;

&lt;p&gt;2개의 플래그를 두고 8개의 상태를표현하면&lt;/p&gt;

&lt;p&gt;,, 각각 flag의 이름은 ft,fw,fh&lt;/p&gt;

&lt;p&gt;기본 = f f f&lt;/p&gt;

&lt;p&gt;좌우 = f t f&lt;/p&gt;

&lt;p&gt;상하 = f f t&lt;/p&gt;

&lt;p&gt;대칭 = f t t&lt;/p&gt;

&lt;p&gt;TP    = t f f&lt;/p&gt;

&lt;p&gt;좌우 = t t f&lt;/p&gt;

&lt;p&gt;상하 = t f t&lt;/p&gt;

&lt;p&gt;대칭 = t t t&lt;/p&gt;

&lt;p&gt;즉 높이H , 너비W 인 비트맵이미지에서&lt;/p&gt;

&lt;p&gt;for (i&amp;lt;H-1   …h++)&lt;/p&gt;

&lt;p&gt;for(i&amp;lt;W-1  …w++) // 메모리접근은 0부터 세므로 각각 -1&lt;/p&gt;

&lt;p&gt;h*row + w&lt;/p&gt;

&lt;p&gt;의 반복으로 모든 픽셀을 순회한다면&lt;/p&gt;

&lt;p&gt;!ft &amp;amp; (    (W+1) * (fh&lt;em&gt;(H-2 * h)+h)        +      fw&lt;/em&gt;(W-2 * w)+w      )&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;ft  &amp;amp; (    (H+1) *  (fh&lt;em&gt;(W-2 * w)+w)      +      fw&lt;/em&gt;(H-2 * h)+h        )&lt;/p&gt;

&lt;p&gt;ft에 따라서 w h 변환 여부 결정 (flag 설정시 w,h를 미리 교환해야할거같다)&lt;/p&gt;

&lt;p&gt;fw에 따라서 좌우반전&lt;/p&gt;

&lt;p&gt;fh에 따라서 상하반전 여부가 결정&lt;/p&gt;

&lt;p&gt;적용해보려면
실제로 비트맵을 그리는 코드를 찾아야할거같습니다&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">평소에 폰을 사용할때 디스플레이의 방향전환, 회전이 발생할때</summary></entry><entry><title type="html">조사</title><link href="https://nivkhdif.github.io/2020-07-29/1" rel="alternate" type="text/html" title="조사" /><published>2020-07-29T00:00:00+00:00</published><updated>2020-07-29T00:00:00+00:00</updated><id>https://nivkhdif.github.io/2020-07-29/1</id><content type="html" xml:base="https://nivkhdif.github.io/2020-07-29/1">&lt;h2 id=&quot;pointlessbooleanexpression-바이트코드&quot;&gt;PointlessBooleanExpression 바이트코드&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\b1ee3a06f14c1ff5dfb88d4a873d87d9.png&quot; alt=&quot;b1ee3a06f14c1ff5dfb88d4a873d87d9.png&quot; /&gt;
to 바이트코드
&lt;img src=&quot;..\assets\8fe3e57fd5b85535eb970dcb07576f2b.png&quot; alt=&quot;8fe3e57fd5b85535eb970dcb07576f2b.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;if문 부터 print 까지 동일한 구조로 컴파일되어&lt;/p&gt;

&lt;p&gt;컴파일러가 미리 최적화를 해줌을 알수있었습니다&lt;/p&gt;

&lt;h2 id=&quot;arraylist-for-loop&quot;&gt;arraylist for loop&lt;/h2&gt;
&lt;p&gt;viewrootimpl . setwindowstopped 의 경우&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\7e29059e4567aa6692fb75c4f29103ec.png&quot; alt=&quot;7e29059e4567aa6692fb75c4f29103ec.png&quot; /&gt;
mwindowstoppedcallbacks.size()를 매번 호출&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\44b57228ed06f7d57ffe16bef198f94d.png&quot; alt=&quot;44b57228ed06f7d57ffe16bef198f94d.png&quot; /&gt;
mWindowstoppedcallbacks 는 WindowStoppedcallback의  arraylist&lt;/p&gt;

&lt;p&gt;windowstoppedcallback은  인터페이스로 바로위에 정의됨&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\f0b369a66674be97f7b032283f046451.png&quot; alt=&quot;f0b369a66674be97f7b032283f046451.png&quot; /&gt;
windowstoppedcallback은 surfaceview의 interface이며&lt;/p&gt;

&lt;p&gt;(=surface가 callback의구현)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\c9ab1d441285b284a52fce71e6244e81.png&quot; alt=&quot;c9ab1d441285b284a52fce71e6244e81.png&quot; /&gt;
interface의 함수 windowstopped를 override 구현&lt;/p&gt;

&lt;p&gt;updatesurface호출시  surfaceview 객체의 msurface를 release&lt;/p&gt;

&lt;p&gt;ㅡㅡ호출&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\722ea84bc20b8713407752747894f7a7.png&quot; alt=&quot;722ea84bc20b8713407752747894f7a7.png&quot; /&gt;
activity의  perforstop 메소드에서&lt;/p&gt;

&lt;p&gt;windowmanagerglobal.setstoppedstate 호출시.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\73352aefb30dd79720b5df53a079e4a2.png&quot; alt=&quot;73352aefb30dd79720b5df53a079e4a2.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;에서 root.setwinodwstooped를호출&lt;/p&gt;

&lt;p&gt;작동==activity가 stop되었을떄,&lt;/p&gt;

&lt;p&gt;activity에 해당하는&lt;/p&gt;

&lt;p&gt;window(=viewrootimpl)객체의 view를 render하는&lt;/p&gt;

&lt;p&gt;메인renderer thread를 stop한후&lt;/p&gt;

&lt;p&gt;메인과 따로도는 surfaceview 의 renderer를&lt;/p&gt;

&lt;p&gt;window가 가진 surface갯수 (mwindowstoppedcallbacks.size())&lt;/p&gt;

&lt;p&gt;만큼 돌면서 전부 종료&lt;/p&gt;

&lt;p&gt;결론== arraylist의  synchronize를위한 코드로보입니다&lt;/p&gt;

&lt;p&gt;일단 호출한 메소드에서 synchronize(mlock)을 걸고, 다른 호출진입지점이 없어보이므로&lt;/p&gt;

&lt;p&gt;size를 매번구하지 않아도 될거같지만 activity작성 하기에따라 예외가 발생할수도있어보입니다.&lt;/p&gt;

&lt;p&gt;그리고 window는 빠르게 화면을 업데이트해야 하는경우 아니면&lt;/p&gt;

&lt;p&gt;surfaceview를 사용하지않고 하더라도 많아야 2개를 사용하는점으로보아&lt;/p&gt;

&lt;p&gt;최적화를 한다해도 그 영향이 크지않을것으로 보입니다.&lt;/p&gt;

&lt;p&gt;다른 size() 함수들도 거의다  arraylist의 concurrency 때문에&lt;/p&gt;

&lt;p&gt;이렇게 작성된듯 보입니다.&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">PointlessBooleanExpression 바이트코드</summary></entry><entry><title type="html">의심가는부분</title><link href="https://nivkhdif.github.io/2020-07-22/11" rel="alternate" type="text/html" title="의심가는부분" /><published>2020-07-22T00:00:00+00:00</published><updated>2020-07-22T00:00:00+00:00</updated><id>https://nivkhdif.github.io/2020-07-22/11</id><content type="html" xml:base="https://nivkhdif.github.io/2020-07-22/11">&lt;h3 id=&quot;성능의심가는-부분들최대한-찾아보기&quot;&gt;성능의심가는 부분들최대한 찾아보기&lt;/h3&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;supresswarnings-관련자료&quot;&gt;supresswarnings 관련자료&lt;/h4&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;viewrootimpl.java

@SuppressWarnings(
{ 
&quot;EmptyCatchBlock&quot;, &quot;PointlessBooleanExpression&quot;
} 
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.lang.SuppressWarning :&lt;/code&gt; 
어노테이션을 사용하여 컴파일 단위의 서브세트와 관련된 
컴파일 경고를 사용하지 않도록 설정할 수 있게 해주는기능.&lt;/p&gt;

&lt;p&gt;-여기서는 2가지의 경고를 제외했는데&lt;/p&gt;

&lt;p&gt;어떤경우에 뜨는 경고들을 억제하는 것인지 정적 코드 분석 도구 Checkstyle 소스포지 (&lt;a href=&quot;https://checkstyle.sourceforge.io&quot;&gt;checkstyle – Checkstyle 8.34&lt;/a&gt;)
에서 관련 경고내용이 실려있습니다.&lt;/p&gt;

&lt;h6 id=&quot;emptycatchblock&quot;&gt;EmptyCatchBlock&lt;/h6&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
// Such empty blocks would be both suppressed: 

try {
  throw new RuntimeException();
} catch (RuntimeException expected) {
}
try {
  throw new RuntimeException();
} catch (RuntimeException ignore) {
}
      
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;..\assets\1456fd3852f288656fa25ef4ef1b2196.png&quot; alt=&quot;1456fd3852f288656fa25ef4ef1b2196.png&quot; /&gt;
&lt;img src=&quot;..\assets\65bf06b0ec1023734f0afc9f1265cdb6.png&quot; alt=&quot;65bf06b0ec1023734f0afc9f1265cdb6.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;주석만있거나&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\c3c721233e8187afe4b0858474ed79f1.png&quot; alt=&quot;c3c721233e8187afe4b0858474ed79f1.png&quot; /&gt;
빈블럭&lt;/p&gt;

&lt;p&gt;주요 클래스에서 약 20개정도 발견할수있었습니다&lt;/p&gt;

&lt;p&gt;###### 2.PointlessBooleanExpression 부분&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     boolean method (string string) {
            return string.endswith (&quot;a&quot;) == true;   // violation
      }      
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; boolean method (string string) {
        return string.endswith (&quot;a&quot;);
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;“a” == true.fasle 등   true.false로 끝나는 의미없는 expression&lt;/p&gt;

&lt;p&gt;발생이유는 자동리팩터링 혹은 , 프로그래머가 알아보기쉬우려고  if(boolean == false)꼴로 풀어쓴것&lt;/p&gt;

&lt;p&gt;위 코드 최적화시 바이트 코드 5byte를 절약가능하다고 합니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;viewrootimpl.java   ㅡ
  
      private void reportNextDraw() {
        if (mReportNextDraw == false) {
            drawPending();
        }
        mReportNextDraw = true;
        }

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;..\assets\61d7cc0e0000b5c904072c3ab86f3a11.png&quot; alt=&quot;61d7cc0e0000b5c904072c3ab86f3a11.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;주요 클래스 검색결과  3개의 경우를 발견할수있었습니다&lt;/p&gt;

&lt;h6 id=&quot;반복문-관련&quot;&gt;반복문 관련&lt;/h6&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;viewrootimpl.java
   
   private final ArrayList&amp;lt;WindowStoppedCallback&amp;gt; mWindowStoppedCallbacks =  new ArrayList&amp;lt;&amp;gt;();
	
	
	
	
    void addWindowStoppedCallback(WindowStoppedCallback c) 
	{ 
        mWindowStoppedCallbacks.add(c);
		
	} 
	
    void removeWindowStoppedCallback(WindowStoppedCallback c) 
	{ 
        mWindowStoppedCallbacks.remove(c);
		
	}  
   
      void setWindowStopped(boolean stopped) {
        if (mStopped != stopped) {
            mStopped = stopped;
            final ThreadedRenderer renderer = mAttachInfo.mThreadedRenderer;
            if (renderer != null) {
                if (DEBUG_DRAW) Log.d(mTag, &quot;WindowStopped on &quot; + getTitle() + &quot; set to &quot; + mStopped);
                renderer.setStopped(mStopped);
            }
            if (!mStopped) {
                scheduleTraversals();
            } else {
                if (renderer != null) {
                    renderer.destroyHardwareResources(mView);
                }
            }

            for (int i = 0; i &amp;lt; mWindowStoppedCallbacks.size(); i++) {
                mWindowStoppedCallbacks.get(i).windowStopped(stopped);
            }
        }
    }

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;setWindowStopped이란 메소드의 끝부분
for문에서 .size()를 호출함.&lt;/p&gt;

&lt;p&gt;private final ArrayList&lt;WindowStoppedCallback&gt; mWindowStoppedCallbacks =  new ArrayList&amp;lt;&amp;gt;();
//WindowStoppedCallback 의 arraylist&lt;/WindowStoppedCallback&gt;&lt;/p&gt;

&lt;p&gt;public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback {
//WindowStoppedCallback은 SurfaceView 클래스로 구현됨&lt;/p&gt;

&lt;p&gt;``&lt;/p&gt;

&lt;p&gt;호출은 windowmanager global&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  public void setStoppedState(IBinder token, boolean stopped) {
        synchronized (mLock) {
            int count = mViews.size();
            for (int i = 0; i &amp;lt; count; i++) {
                if (token == null || mParams.get(i).token == token) {
                    ViewRootImpl root = mRoots.get(i);
                    root.setWindowStopped(stopped);
                }
            }
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;ViewRootImple 객체인  mRoot를 돌면서  전부 정지??
..
정말 필요해서 size를 매번 구하는건지 좀더 파악해야 알수있을것같습니다&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;..\assets\e861d81eaac63dbe9ef39cb81d16278c.png&quot; alt=&quot;e861d81eaac63dbe9ef39cb81d16278c.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;view 디렉토리 내 주요 java클래스에서 검색한결과&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">성능의심가는 부분들최대한 찾아보기</summary></entry><entry><title type="html">if문</title><link href="https://nivkhdif.github.io/2020-07-02/if" rel="alternate" type="text/html" title="if문" /><published>2020-07-02T00:00:00+00:00</published><updated>2020-07-02T00:00:00+00:00</updated><id>https://nivkhdif.github.io/2020-07-02/if</id><content type="html" xml:base="https://nivkhdif.github.io/2020-07-02/if">&lt;p&gt;확인방법: 바이트코드&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;
if(a &amp;amp;&amp;amp; b &amp;amp;&amp;amp; c &amp;amp;&amp;amp; d &amp;amp;&amp;amp; e &amp;amp;&amp;amp; f &amp;amp;&amp;amp; g)
&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if(a)
 if(b)
  if(c)
   if(d)
    if(e)
     if(f)
      if(g)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;:둘다 동일한 바이트코드로 컴파일됨.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;boolean a=true, b=true, c=true, d=true, e=true, f=true, g=true;
   0: iconst_1
   1: istore_1
   2: iconst_1
   3: istore_2
   4: iconst_1
   5: istore_3
   6: iconst_1
   7: istore        4
   9: iconst_1
  10: istore        5
  12: iconst_1
  13: istore        6
  15: iconst_1
  16: istore        7

if(a &amp;amp;&amp;amp; b &amp;amp;&amp;amp; c &amp;amp;&amp;amp; d &amp;amp;&amp;amp; e &amp;amp;&amp;amp; f &amp;amp;&amp;amp; g) {}
  18: iload_1
  19: ifeq          45
  22: iload_2
  23: ifeq          45
  26: iload_3
  27: ifeq          45
  30: iload         4
  32: ifeq          45
  35: iload         5
  37: ifeq          45
  40: iload         6
  42: ifeq          45

if(a) if(b) if(c) if(d) if(e) if(f) if(g) {}
  45: iload_1
  46: ifeq          72
  49: iload_2
  50: ifeq          72
  53: iload_3
  54: ifeq          72
  57: iload         4
  59: ifeq          72
  62: iload         5
  64: ifeq          72
  67: iload         6
  69: ifeq          72
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;최적화&quot;&gt;최적화&lt;/h4&gt;

&lt;h2 id=&quot;1스위치문&quot;&gt;1.스위치문&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public int calculate(int a, int b, String operator) {
    int result = Integer.MIN_VALUE;
 
    if (&quot;add&quot;.equals(operator)) {
        result = a + b;
    } else if (&quot;multiply&quot;.equals(operator)) {
        result = a * b;
    } else if (&quot;divide&quot;.equals(operator)) {
        result = a / b;
    } else if (&quot;subtract&quot;.equals(operator)) {
        result = a - b;
    }
    return result;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public int calculateUsingSwitch(int a, int b, String operator) {
    switch (operator) {
    case &quot;add&quot;:
        result = a + b;
        break;
    // other cases    
    }
    return result;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;장점 : 간단, 유지보수용이
단점 : 복잡한논리엔 부적합&lt;/p&gt;

&lt;h2 id=&quot;리팩토링&quot;&gt;리팩토링&lt;/h2&gt;

&lt;p&gt;3.1 팩토링클래스 ::원하는 타입 객체를 반환&lt;/p&gt;

&lt;p&gt;연산 인터페이스&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public interface Operation {
    int apply(int a, int b);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;구현&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class Addition implements Operation {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;구현클래스들의 hashmap소유  클래스
//map으로 두면 더빠름&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class OperatorFactory {
    static Map&amp;lt;String, Operation&amp;gt; operationMap = new HashMap&amp;lt;&amp;gt;();
    static {
        operationMap.put(&quot;add&quot;, new Addition());
        operationMap.put(&quot;divide&quot;, new Division());
        // more operators
    }
 
    public static Optional&amp;lt;Operation&amp;gt; getOperation(String operator) {
        return Optional.ofNullable(operationMap.get(operator));
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;숫자, 연산자를 받아  , 팩터링클래스에 넘긴후 객체를 return받기&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public int calculateUsingFactory(int a, int b, String operator) {
    Operation targetOperation = OperatorFactory
      .getOperation(operator)
      .orElseThrow(() -&amp;gt; new IllegalArgumentException(&quot;Invalid Operator&quot;));
    return targetOperation.apply(a, b);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;32-enums&quot;&gt;3.2 Enums&lt;/h2&gt;

&lt;p&gt;logic에 enum 부여 ,if , switch , factor의 조건으로 사용&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;연산 label 지정
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public enum Operator {
 ADD, MULTIPLY, SUBTRACT, DIVIDE
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;구현&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ADD {
    @Override
    public int apply(int a, int b) {
        return a + b;
    }
},
// other operators
 
public abstract int apply(int a, int b);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;3.라우터&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public int calculate(int a, int b, Operator operator) {
    return operator.apply(a, b);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Operator#valueOf() method 로  String 을 operator로 변환해서 사용&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@Test
public void whenCalculateUsingEnumOperator_thenReturnCorrectResult() {
    Calculator calculator = new Calculator();
    int result = calculator.calculate(3, 4, Operator.valueOf(&quot;ADD&quot;));
    assertEquals(7, result);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;33명령패턴&quot;&gt;3.3명령패턴&lt;/h2&gt;

&lt;p&gt;명령을받는 Calculator#calculate   which can be executed on the inputs.
//중첩 if 개선&lt;/p&gt;

&lt;p&gt;1.커맨드&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public interface Command {
    Integer execute();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;2.add커맨드&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class AddCommand implements Command {
    // Instance variables
 
    public AddCommand(int a, int b) {
        this.a = a;
        this.b = b;
    }
 
    @Override
    public Integer execute() {
        return a + b;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;3.command를 받는 method&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public int calculate(Command command) {
    return command.execute();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;4.AddCommand객체생성, Calculator#calculate method에 보내기:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@Test
public void whenCalculateUsingCommand_thenReturnCorrectResult() {
    Calculator calculator = new Calculator();
    int result = calculator.calculate(new AddCommand(3, 7));
    assertEquals(10, result);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;34룰엔진&quot;&gt;3.4룰엔진&lt;/h2&gt;

&lt;p&gt;중첩 if문 평가 규칙
규칙과 입력에따라 반환 복잡성제거&lt;/p&gt;

&lt;p&gt;1.rule&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public interface Rule {
    boolean evaluate(Expression expression);
    Result getResult();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;2.rule engine&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class RuleEngine {
    private static List&amp;lt;Rule&amp;gt; rules = new ArrayList&amp;lt;&amp;gt;();
 
    static {
        rules.add(new AddRule());
    }
 
    public Result process(Expression expression) {
        Rule rule = rules
          .stream()
          .filter(r -&amp;gt; r.evaluate(expression))
          .findFirst()
          .orElseThrow(() -&amp;gt; new IllegalArgumentException(&quot;Expression does not matches any Rule&quot;));
        return rule.getResult();
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;RuleEngine은 Expression object를받아  결과반환 
Expression:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class Expression {
    private Integer x;
    private Integer y;
    private Operator operator;        
}        //두 정수와 연산의 expression
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;addrule&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class AddRule implements Rule {
    @Override
    public boolean evaluate(Expression expression) {
        boolean evalResult = false;
        if (expression.getOperator() == Operator.ADD) {
            this.result = expression.getX() + expression.getY();
            evalResult = true;
        }
        return evalResult;
    }    
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;호출: engin.process(expression)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@Test
public void whenNumbersGivenToRuleEngine_thenReturnCorrectResult() {
    Expression expression = new Expression(5, 5, Operator.ADD);
    RuleEngine engine = new RuleEngine();
    Result result = engine.process(expression);
 
    assertNotNull(result);
    assertEquals(10, result.getValue());
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;assert문::    //jdk1.4 이상&lt;/p&gt;

&lt;p&gt;assert expression1;      //참:pass  거짓:AssertionError&lt;/p&gt;

&lt;p&gt;assert expression1: expression2;       //exp1참 : pass 거짓 : exp2출력&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;출처::&lt;/p&gt;

&lt;p&gt;https://www.baeldung.com/java-replace-if-statements&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">확인방법: 바이트코드</summary></entry><entry><title type="html">윈도우 매니저</title><link href="https://nivkhdif.github.io/2020-05-13/wm" rel="alternate" type="text/html" title="윈도우 매니저" /><published>2020-05-13T00:00:01+00:00</published><updated>2020-05-13T00:00:01+00:00</updated><id>https://nivkhdif.github.io/2020-05-13/wm</id><content type="html" xml:base="https://nivkhdif.github.io/2020-05-13/wm">&lt;details&gt;
    &lt;summary&gt;SurfaceFlinger:: &lt;/summary&gt;
    
    
여러 개의 Surface를 하나의 Surface로 만들고 

만든 화면을 프레임 버퍼 드라이버와 

연계하여 프레임 버퍼로 만들고, (프레임버퍼에 등록?)LCD 화면에 표시하는 역할

    
&lt;/details&gt;
&lt;p&gt;surface :: 창&lt;/p&gt;

&lt;p&gt;새창추가 = 새 surface할당&lt;/p&gt;

&lt;h2 id=&quot;windowmanager----------애플리케이션과-windowmanagerserivce--간의-소통interface&quot;&gt;WindowManager         :: 애플리케이션과 WindowManagerSerivce  간의 소통interface&lt;/h2&gt;

&lt;p&gt;ViewManager를 상속하여 구현됨&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public interface ViewManager{
    / / Add View
    public void addView(View view, ViewGroup.LayoutParams params);
    / / Update View
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    / / Delete View
    public void removeView(View view);
}Copy code
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;1.Add 
2.Update
3.Delete 
ㅡ3개의 method를 가짐&lt;/p&gt;

&lt;h2 id=&quot;windowmanager-의-구현클래스--windowmanagerimpl&quot;&gt;WindowManager 의 구현클래스 = WindowManagerImpl&lt;/h2&gt;

&lt;h2 id=&quot;windowmanagerimpl의-기능구현클래스--windowmanagerglobal&quot;&gt;WindowManagerImpl의 기능구현클래스 = WindowManagerGlobal&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public final class WindowManagerGlobal {
 
     public void addView(View view, ViewGroup.LayoutParams params,
                Display display, Window parentWindow) {
            / / Check the validity of the parameters
            ...
 
            //ViewRootImpl encapsulates the interaction between View and WindowManager
            ViewRootImpl root;
            View panelParentView = null;
 
            synchronized (mLock) {
                // Start watching for system property changes.
                if (mSystemPropertyUpdater == null) {
                    mSystemPropertyUpdater = new Runnable() {
                        @Override public void run() {
                            synchronized (mLock) {
                                for (int i = mRoots.size() - 1; i &amp;gt;= 0; --i) {
                                    mRoots.get(i).loadSystemProperties();
                                }
                            }
                        }
                    };
                    SystemProperties.addChangeCallback(mSystemPropertyUpdater);
                }
 
                int index = findViewLocked(view, false);
                if (index &amp;gt;= 0) {
                    if (mDyingViews.contains(view)) {
                        // Don't wait for MSG_DIE to make it's way through root's queue.
                        mRoots.get(index).doDie();
                    } else {
                        throw new IllegalStateException(&quot;View &quot; + view
                                + &quot; has already been added to the window manager.&quot;);
                    }
                    // The previous removeView() had not completed executing. Now it has.
                }
 
                // If this is a panel window, then find the window it is being
                // attached to for future reference.
                if (wparams.type &amp;gt;= WindowManager.LayoutParams.FIRST_SUB_WINDOW &amp;amp;&amp;amp;
                        wparams.type &amp;lt;= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                    final int count = mViews.size();
                    for (int i = 0; i &amp;lt; count; i++) {
                        if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
                            panelParentView = mViews.get(i);
                        }
                    }
                }
 
                / / Build ViewRootImpl through the context
                root = new ViewRootImpl(view.getContext(), display);
 
                view.setLayoutParams(wparams);
 
                //mViews stores all View objects corresponding to Window
                mViews.add(view);
                //mRoots stores all ViewRootImpl objects corresponding to Window
                mRoots.add(root);
                //mParams stores all WindowManager.LayoutParams objects corresponding to Window
                mParams.add(wparams);
            }
 
            // do this last because it fires off messages to start doing things
            try {
                / / Call the ViewRootImpl.setView () method to complete the addition of Window and update the interface
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                synchronized (mLock) {
                    final int index = findViewLocked(view, false);
                    if (index &amp;gt;= 0) {
                        removeViewLocked(index, true);
                    }
                }
                throw e;
            }
        }
 
}Copy code
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;중요멤버&lt;/p&gt;

&lt;p&gt;mViews    view 객체 저장&lt;/p&gt;

&lt;p&gt;mRoots   ViewRootImpl  객체 저장&lt;/p&gt;

&lt;p&gt;mParams WindowManager.LayoutParams 객체 저장&lt;/p&gt;

&lt;p&gt;ViewRootImpl 클래스::
View와  WindowManager간 상호작용을 캡슐화하는 래퍼클래스&lt;/p&gt;

&lt;p&gt;ViewRootImpl.setView() 호출
:::창의 추가와 업데이트완료를 위해&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">SurfaceFlinger:: 여러 개의 Surface를 하나의 Surface로 만들고</summary></entry><entry><title type="html">바인더 관련</title><link href="https://nivkhdif.github.io/2020-04-08/binder" rel="alternate" type="text/html" title="바인더 관련" /><published>2020-04-08T00:00:01+00:00</published><updated>2020-04-08T00:00:01+00:00</updated><id>https://nivkhdif.github.io/2020-04-08/binder</id><content type="html" xml:base="https://nivkhdif.github.io/2020-04-08/binder">&lt;h2 id=&quot;바인더&quot;&gt;바인더&lt;/h2&gt;

&lt;p&gt;원래 IPC(Inter Process Communication) 도구이지만 안드로이드에서는 다른 프로세스에 있는 함수를 마치 현재 프로세스에 존재하는 함수처럼 사용할 수 있게 해주는 RPC(Remote Procedure Call)를 지원하는 데 주로 이용&lt;/p&gt;

&lt;p&gt;안드로이드에서 바인더 드라이버를 추가해서 프로세스 간 통신을 수행하는 이유?&lt;/p&gt;

&lt;p&gt;리눅스의 뛰어난 메모리 관리 기법을 그대로 채용함으로써 커널 공간을 통한 데이터 전달시 데이터의 신뢰성을 확보&lt;/p&gt;

&lt;p&gt;사용자 공간에서 접근할 수 없는 공간인 커널 공간을 이용해 데이터를 주고 받기 때문에 IPC 간의 보안 문제도 동시에 해결&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://d2.naver.com/content/images/2015/06/helloworld-47656-7.png&quot; alt=&quot;d&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;카메라앱의-바인더호출&quot;&gt;카메라앱의 바인더호출&lt;/h2&gt;

&lt;p&gt;Camera 서비스의 내부 동작&lt;/p&gt;

&lt;p&gt;Camera.cpp는 Camera::getCameraService()를 통해서 ICameraService 를 호출한다.&lt;/p&gt;

&lt;p&gt;실제는 BpCameraService가 호출될 때 이루어진다. BpCameraService는 binder를 통해서 두 프로세스 사이의 BnCameraService 통신채널을 생성한다. BpCamera Service의 connect()함수에서는 다음과 같이 BnCamera Service를 연결시키는 부분이 있다.&lt;/p&gt;

&lt;p&gt;remote()-&amp;gt;transact(BnCameraService::CONNECT, data, &amp;amp;reply);&lt;/p&gt;

&lt;p&gt;Camera server로의 서비스 요청&lt;/p&gt;

&lt;p&gt;카메라 서비스로의 접속은 서비스 매니저로부터 Camera Service를 담당하는 binder class인 ICamera Service를 get함으로써 이루어진다. 물론, 그 전에 ICameraClient 형의 Camera class를 생성함으로써 Camera client로부터 Camera server(카메라 서비스)로의 Binder 연결이 이루어진다.&lt;/p&gt;

&lt;p&gt;CONNECT command를 통해서 카메라 서비스로 접속을 하게 되면 카메라 서비스 쪽에서는 server에서 client로 접속되는 ICamera 형의 client class를 생성해서 Camera client 쪽으로 할당해 준다. ICameraService를 이용한 Binder interface는 CONNECT command외에 다른 command는 존재하지 않는다. 이 Class는 오직 connect를 받아서 새로운 Binder를 생성(server에서 client로의 data 통로를 여는)하기만 할 뿐이다.&lt;/p&gt;

&lt;p&gt;위의 메커니즘 설명은 이러한 부분에 대한 기술적인 설명을 하는 부분이 된다. IPC인 Binder 부분은 실제 호출되는 부분과 실행되는 부분이 감추어져 있기 때문에 코드에 대한 추적이 어렵다.&lt;/p&gt;

&lt;p&gt;즉, ICameraService.cpp의 BpCameraService의 connect()를 통해, CameraService.cpp의 Camera&lt;/p&gt;

&lt;p&gt;Service::onTransact() 로 아래의 내용을&lt;/p&gt;

&lt;p&gt;status_t err = BnCameraService::onTransact(code, data, reply, flags);&lt;/p&gt;

&lt;p&gt;호출함으로써 두 개의 프로세스간 BnCameraService()통신채널을 구성하게 된다. 실제 BpCameraService의 구현은 CameraServicce에서 이루어진다고 보면 된다. Camera.cpp는 다른 프로세스로 동작 하지만, 그 인터페이스는 ICameraService의 connect()를 호출함으로써 CameraService의 ICamera class인 CameraService:: Client를 획득할 수 있게 된다. Camera에 관련된 함수들은 CameraService:: Client 가 생성되면서 실제로 구현된다.&lt;/p&gt;

&lt;p&gt;출처 : 테크월드(http://www.epnc.co.kr)&lt;/p&gt;</content><author><name>im jin hyeon</name><email>evigt3242@gmail.com</email></author><summary type="html">바인더</summary></entry></feed>