顯示具有 Android 標籤的文章。 顯示所有文章
顯示具有 Android 標籤的文章。 顯示所有文章

2020年9月21日 星期一

[Android] Android SystemProperties應用

import android.os.SystemProperties;


String prop_name = "persist.car.system_type"

if ("0".equals(SystemProperties.get( prop_name)))  //比對prop_name值 == 0

{

    //比對prop_name值 == 0

}else

{

    //比對prop_name值 != 0(不等於0)

}

2020年9月16日 星期三

[Android] 使用dd及還原工具進行Android系統的還原

因美國專案人員使用fastboot命令更新rom導致開機失敗(燒壞),亦無法繼續更新
需線上提供dd image進行緊急燒路更新。 以dd來說是以整張SD卡磁區作為備份image
再利用工具Wim32DiskImager 將備份之image還原至另一張SD卡的方法。適合用於緊急狀況
但也需要相對大的空間(因為是將燒錄後展開的系統整張卡片打包成image的緣故)


Stpe1. 使用dd 命令製作image

dd if=/dev/sdb/ of=./aaa.img bs=512



Stpe2. 格式化SD卡

使用SD Card Formater : https://www.sdcard.org/downloads/index.html


Stpe3. Win32DiskImager : https://sourceforge.net/projects/win32diskimager/



























或是使用 USB image tool : https://www.alexpage.de/usb-image-tool/download/





2020年8月10日 星期一

[Android]Camera debug for nv 21 and 12 format

 RAW pixels viewer(免安裝的網路資源) : https://rawpixels.net/

7yuv(需下載安裝於電腦中) : http://datahammer.de/



類似RGB的概念 : YUV也是三種色彩元素代稱, Y=明亮度, U=色度, V=濃度

YUV為視訊影像的編碼格式 目前專案僅用到N21與N12兩種格式的驗證應用

YUV文獻 : https://www.itread01.com/content/1542704886.html

N21與N12根據定義為YUV中 UV順序相反,

N21為Y填完再用UV交替填完,例 : YYYYVUVUVU

YUV格式中又分為YUV444,YUV422,YUV420 

     1.YUV 4:4:4取樣,每一個Y對應一組UV分量,一個YUV佔8+8+8 = 24bits 3個位元組。

     2.YUV 4:2:2取樣,每兩個Y共用一組UV分量,一個YUV佔8+4+4 = 16bits 2個位元組。

     3.YUV 4:2:0取樣,每四個Y共用一組UV分量,一個YUV佔8+2+2 = 12bits 1.5個位元組。

YUV420中又分為,YUV420SP與YUV420P


在camera相關案子得應用中有平台影響推流的問題待釐清,就順勢追了一下code

private final Timer timer = new Timer();

private final TimerTask tickTask = new TimerTask() {

public void run() {

VirtualCameraCapturer.this.tick();

}};

private void tick() {

// Log.d("CAM_AntiPushEngine", "VirtualCameraCapturer frame=" + frame + " buffersize=" + frame.getBuffer().getHeight());

capturerObserver.onFrameCaptured(frame);

}


其中frame由另一函式放張圖片來更新再透過tick作推送

try {

            Log.d(TAG, "VirtualCameraCapturer...1");

            inputStream = context.getAssets().open("clip_480x360_Format-0.yuv");

            int size = 480 * 360 * 3 / 2;

            byte[] data = new byte[size];

            inputStream.read(data, 0, size);

            Log.v("NV12","KH123");

            VideoFrame.Buffer frameBuffer = new NV12Buffer(480, 360, 480, 360, ByteBuffer.wrap(data), new Runnable() {

            //VideoFrame.Buffer frameBuffer = new NV21Buffer(data, 480, 360, new Runnable() {

                @Override

                public void run() {

                    Log.d("lhq", "NV21Buffer release");

                }

            });

            Log.v("NV12","KH456");

            long captureTimeNs = TimeUnit.MILLISECONDS.toNanos(SystemClock.elapsedRealtime());

            frame = new VideoFrame(frameBuffer, 0, captureTimeNs);

            Log.v(TAG, "VirtualCameraCapturer...2");

        } catch (IOException e) {

            e.printStackTrace();

        }


由上述程式碼可看到 應用程式新增一個timer tick去定期將camera擷取到的影像frame推送到onFrameCaptured裡面。


此時我們追到另一個code base使用Find in path看誰會去呼叫onFrameCaptured函式。

在webrtc中的Camera1Session.javad查詢到

 private void listenForTextureFrames() {

private void listenForBytebufferFrames() {

會使用到onFrameCaptured


在 listenForTextureFrames()中可在以下程式碼段前後擷取出raw data看其格式及圖片檢查是否正確

inal VideoFrame modifiedFrame = new VideoFrame(

          CameraSession.createTextureBufferWithModifiedTransformMatrix(

              (TextureBufferImpl) frame.getBuffer(),

              /* mirror= */ info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT,

              /* rotation= */ 0),

          /* rotation= */ getFrameOrientation(), frame.getTimestampNs());

      Log.v(TAG, "Modified frame");









2020年7月22日 星期三

[Android]Framework相關修改路徑

替換底圖
9.0版本
android_build/device/fsl/imx8q/mek_8q/overlay/frameworks/base/core/res/res

改版號
android_build/device/fsl/imx8q/mek_8q/build_id.mk

改alsa source code
android_build/vendor/nxp-opensource/imx/alsa


清除版號暫存
rm -rf out/target/product/mek_8q/obj/ETC/system_build_prop_intermediates/


SystemUI 路徑
android_build/framworks/base/packages/SystemUI/


應用程式全螢幕規則修改
services/core/java/com/android/server/policy/PhoneWindowManager.java
String window Title = attrs.getTitle().toString();
boolean shouldLetAppFullScreen = windowTitle.contains("CarThemeWindow")
|| window Title.contains(".....")...
...




2020年7月16日 星期四

[Android]Android 8.1&9.0 支持多應用同時錄音解決方法

Android Audio - 支持多应用同时录音_Android8.1修改方法 : https://blog.csdn.net/qq_33443989/article/details/103721204


Android Audio - 支持多应用同时录音_Android9.0修改方法 : https://blog.csdn.net/qq_33443989/article/details/106763214

2020年4月12日 星期日

[Android]Android OTA & fastboot method 與avc dennied(sepolicy裡.te檔的變更規則)的解決方法

A/B(无缝)系统更新 : https://source.android.google.cn/devices/tech/ota/ab

OTA
Android SELinux avc dennied权限问题解决方法 : https://blog.csdn.net/tung214/article/details/72734086

Android Update Engine分析(三)客户端进程 : https://blog.csdn.net/guyongqiangx/article/details/80820399

三、A/B 升级update_engine分析-客户端 : https://blog.csdn.net/Android_2016/article/details/102912357

Android SELinux avc dennied权限问题解决方法 : https://my.oschina.net/kingchen8080/blog/2876363
android selinux : https://blog.csdn.net/u012719256/article/details/52094713



圖片可能會因為太久而遺失,以下多拿幾個error log範例來說明 : 

[ 4237.537022] type=1400 audit(1568869525.184:24238): avc: denied { dac_read_search } for pid=3640 comm="Binder:3640_6" capability=2 scontext=u:r:installd:s0 tcontext=u:r:installd:s0 tclass=capability permissive=0 duplicate messages suppressed
[ 4237.537048] type=1400 audit(1568869535.920:25782): avc: denied { dac_read_search } for pid=3640 comm="Binder:3640_7" capability=2 scontext=u:r:installd:s0 tcontext=u:r:installd:s0 tclass=capability permissive=0
[ 5091.489268] type=1400 audit(1568870379.416:30542): avc: denied { dac_read_search } for pid=3640 comm="Binder:3640_7" capability=2 scontext=u:r:installd:s0 tcontext=u:r:installd:s0 tclass=capability permissive=0 duplicate messages suppressed
[ 5091.489296] type=1400 audit(1568870389.864:32086): avc: denied { dac_read_search } for pid=3640 comm="Binder:3640_6" capability=2 scontext=u:r:installd:s0 tcontext=u:r:installd:s0 tclass=capability permissive=0


修改規則 : 
"comm"+te -> allow "comm" object_r:tclass { "denied_permission" };



A/B system <二> update_engine_client : http://hooltech.com/2018/08/07/ab_system-20-00/#ab-system--update_engine_client
查了老半天發現主要還是餵給update_engine_client格式的問題
正確如下 :
隨身碟 :
update_engine_client  --payload=file:///mnt/media_rw/707B-88DE/payload.bin --update --headers="FILE_HASH=/VSC4qnNIG4jpGgQIZKF/jqTNVOUWR7bO3H7mHl/Dug=
FILE_SIZE=463764699
METADATA_HASH=DKzdifBcuHUuIfgYJjjj3EAprqfiPOnfZWbex35wNVI=
METADATA_SIZE=58918"

SD Card :
update_engine_client  --payload=file:///sdcard/payload.bin --update --headers="FILE_HASH=/VSC4qnNIG4jpGgQIZKF/jqTNVOUWR7bO3H7mHl/Dug=
FILE_SIZE=463764699
METADATA_HASH=DKzdifBcuHUuIfgYJjjj3EAprqfiPOnfZWbex35wNVI=
METADATA_SIZE=58918"


附圖 :









fastboot方法 : 

$adb root
$adb shell reboot bootloader

$fastboot flashing unlock #Android OEM unlocking "Enable" first   如果無法順利使用fastboot必須在開發者模式解鎖OEM鎖

$fastboot flash bootloader0 u-boot-imx8qm.imx
$fastboot flash gpt partition-table.img
$fastboot flash dtbo_a dtbo-imx8qm-hdmi.img
$fastboot flash dtbo_b dtbo-imx8qm-hdmi.img
$fastboot flash boot_a boot.img
$fastboot flash boot_b boot.img
$fastboot flash system_a system.img
$fastboot flash system_b system.img
$fastboot flash vendor_a vendor.img
$fastboot flash vendor_b vendor.img
$fastboot --disable-verification flash vbmeta_a vbmeta-imx8qm-hdmi-in.img
$fastboot --disable-verification flash vbmeta_b vbmeta-imx8qm-hdmi.img
#fastboot erase userdata (if partition size change)
$fastboot reboot


















Recovery


看起來是把ota image檔案放到   /cache/update.zip
然後執行下述指令就可以了,

mkdir -p /cache/recovery
touch /cache/recovery/command
echo "--update_package=/cache/update.zip" > /cache/recovery/command
reboot recovery


測試時使用 adb root

2020年1月15日 星期三

[Android]BitmapFactory.decodeResource在設定圖檔發生大小不一致的問題


最近在開發android media player的專輯封面圖檔
發現會有圖檔設定大小不符合預期的情形 如下面所述程式碼
mBitmap = getMirrorBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.cluster_media_music_icon_albums_disable) , percent);

埋log發現不符合大小是該行程式碼所引起,因此特別去搜尋 找到網路上有些關文章討論跟我發生一樣狀況的文章
BitmapFactory.decodeResource之坑 :https://www.itread01.com/content/1546283285.html


Bitmap resize api
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
    int width = bm.getWidth();    int height = bm.getHeight();    float scaleWidth = ((float) newWidth) / width;    float scaleHeight = ((float) newHeight) / height;    // CREATE A MATRIX FOR THE MANIPULATION    Matrix matrix = new Matrix();    // RESIZE THE BIT MAP    matrix.postScale(scaleWidth, scaleHeight);    // "RECREATE" THE NEW BITMAP    Bitmap resizedBitmap = Bitmap.createBitmap(
            bm, 0, 0, width, height, matrix, false);    //bm.recycle();    return resizedBitmap;}

2019年12月16日 星期一

[Android] ArrayList + Hashmap 鍵值索引混合應用

package com.example.arraylistadapter;

import androidx.appcompat.app.AppCompatActivity;

import android.bluetooth.BluetoothDevice;
import android.os.Bundle;
import java.util.Collections;
import java.util.ArrayList;
import java.util.HashMap;

import android.util.Log;

public class MainActivity extends AppCompatActivity {

    private ArrayList LocalList = new ArrayList(5);
    private HashMap LocalListDetail = new HashMap(5);

    private int addLocalList(String dev_name, String Addr) {
        int index = -1;
        boolean isDuplicate = false;
        isDuplicate = LocalList.contains(dev_name);
        if (LocalList.isEmpty()){
            LocalList.add(dev_name);
        }else if ((!LocalList.isEmpty())&& (!isDuplicate))
        {
            if (LocalList.size() == 1)
            {
                LocalList.add(dev_name);
                Collections.reverse(LocalList);
            }
            else
                {
                isDuplicate = LocalList.contains(dev_name);
                Collections.reverse(LocalList);
                LocalList.add(dev_name);
                Collections.reverse(LocalList);
                index = LocalList.indexOf(dev_name);
            }
        }
        isDuplicate = LocalListDetail.containsKey(dev_name);
        if (!isDuplicate) {
            LocalListDetail.put(dev_name, Addr);
        }
        Log.v("LOG", "Added success, start to query all local list.");
        queryAllLocalList();
        return index;
    }

    private void deleteLocalList(int key_position)
    {
        int index = -1;
        String getResult = "";
        boolean isContains = false;
        if((key_position >= 0) && (key_position <= 4))
        {
            getResult = (String)LocalList.get(key_position);
            isContains = LocalListDetail.containsKey(getResult);
            if(isContains)
                LocalListDetail.remove(getResult);
            try {
                LocalList.remove(key_position);
                Log.v("LOG", "Delete " + key_position + "th data success");
            }catch(Exception e)
            {
                Log.v("LOG", "Delete enter into try catch exception");
            }
        }
        Log.v("LOG", "Start to query all local list.");
        queryAllLocalList();
    }

    public void modifyLocalList(int key_position, String dev_name, String Addr)
    {
        int index = -1;
        String getResult = "";
        boolean isContains = false;
        if((key_position >= 0) && (key_position <= 4))
        {
            getResult = (String)LocalList.get(key_position);
            isContains = LocalListDetail.containsKey(getResult);
            if(isContains) {
                LocalListDetail.remove(getResult);
                LocalListDetail.put(dev_name, Addr);
            }else{
                LocalListDetail.put(dev_name, Addr);
            }
            LocalList.set(key_position, dev_name);
            Log.v("LOG", "modify success");
        }
        queryAllLocalList();
    }

    public String queryLocalList(int key_position)
    {
        String getResult = null;
        String totalResult = null;
        boolean isContains = false;
        if((key_position >= 0) && (key_position <= 4))
        {
            try
            {
                getResult = (String)LocalList.get(key_position);
                isContains = LocalListDetail.containsKey(getResult);
                if (!isContains)
                {
                    Log.v("LOG", "query LocalList and LocalListDetail not match");
                    totalResult = "LocalList(" + key_position + ") value = " + getResult;
                    return totalResult;
                }
                totalResult = "LocalList(" + key_position + ") device_name = " + getResult + "addr = " + LocalListDetail.get(getResult);
                Log.v("LOG", totalResult);
            }catch(Exception e){
                //e.printStackTrace();
                totalResult = "key_position index(" + key_position + ") fail";
                Log.v("LOG", totalResult);
            }
        }
        return totalResult;
    }

    public void queryAllLocalList()
    {
        for(int index = 0; index< 5; index++)
            queryLocalList(index);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int s_index= -1;

        //Add
        s_index = addLocalList("kh's iphone", "aa:bb:cc:ee:dd:ff");
        Log.v("LOG", "s_index = " + s_index);
        s_index = addLocalList("kp's iphone", "aa:bb:cc:ee:dd:ff");
        Log.v("LOG", "s_index = " + s_index);

        s_index = addLocalList("scott's iphone", "bb:aa:ee:cc:dd:ff");
        Log.v("LOG", "s_index = " + s_index);

        s_index = addLocalList("Ivan's iphone", "ee:aa:ee:cc:dd:ff");
        Log.v("LOG", "s_index = " + s_index);

        s_index = addLocalList("CK's iphone", "dd:aa:cc:cc:dd:ff");
        Log.v("LOG", "s_index = " + s_index);

        //Delete
        deleteLocalList(0);
        deleteLocalList(2);

        //Modify
        modifyLocalList(0, "jj's i10Plus", "ff:ee:dd:cc:bb:aa");

        //Query
        queryLocalList(0);
        queryLocalList(1);

        //QueryAll
        queryAllLocalList();

//        a.add("011");
//        a.add("111");
//        a.add("211");
//        a.add("311");
//        a.add("411");
//        Log.v("LOG", "a" + a.toString());
//        //ccc = a.size();
//        a.remove(2);
//        String ccc = (String)a.get(2);
//
//        int locate = a.indexOf("411");
//        Log.v("LOG", "411 = " + locate);
//        Log.v("LOG", "ccc = " + ccc);
//
//        Log.v("LOG", "a" + a.toString());
//        //System.out.println("ArrayList: " + a);
//
//        // populate hash map
//        newmap.put("111", "tutorials");
//        newmap.put("222", "point");
//        newmap.put("333", "is best");
//
//        // get value of key 3
//        String val=(String)newmap.get("111");
//
//        // check the value
//        System.out.println("Value for key 3 is: " + val);
    }
}

2019年12月8日 星期日

[Android] frame, UI debug print log

Exception ee = new Exception();
ee.printStackTrace();

2019年12月2日 星期一

[Android]Android BT avrcp framework層巡禮

爬了一整圈Android BT framework的sourcecode 看到這篇,有些坑也提到了就引用分享一下 :
https://www.twblogs.net/a/5c00cab5bd9eee7aed3391cf

接收intent註冊

IntentFilter filter2 = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
//filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
//filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothA2dpSink.ACTION_PLAYING_STATE_CHANGED);
filter.addAction(BluetoothAvrcpController.ACTION_TRACK_EVENT);
filter.addAction(BluetoothAvrcpController.ACTION_PLAYER_SETTING);
filter.addAction(Constants.ACTION_AVRCP_CMD);
mContext.registerReceiver(mBTReceiver, filter);


private BroadcastReceiver mBTReceiver = new BroadcastReceiver() {
@Override

public void onReceive(Context context, Intent intent) {

// Log.d(TAG, "mBTReceiver " + intent.getAction());

// showToast(intent.getAction());

if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction()))

{

int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);

if (state == BluetoothAdapter.STATE_ON)

{

Log.d(LOG_TAG, "BT ON");

}

else if( state == BluetoothAdapter.STATE_OFF)

{

Log.d(LOG_TAG, "BT OFF");

setBtStatus(BtStatus.BT_DISCONNECT);

}

}

else if( BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction()) ) {

int previous_state = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothA2dpSink.STATE_DISCONNECTED);

int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothA2dpSink.STATE_DISCONNECTED);

if( state == BluetoothA2dpSink.STATE_CONNECTING) {

Log.d(LOG_TAG, "A2DPSink STATE_CONNECTING");

} else if( state == BluetoothA2dpSink.STATE_CONNECTED) {

Log.d(LOG_TAG, "A2DPSink STATE_CONNECTED");

setBtStatus(BtStatus.BT_CONNECT);

} else if (state == BluetoothA2dpSink.STATE_DISCONNECTED) {

Log.d(LOG_TAG, "A2DPSink STATE_DISCONNECTED");

setBtStatus(BtStatus.BT_DISCONNECT);

}

}

else if(BluetoothA2dpSink.ACTION_PLAYING_STATE_CHANGED.equals(intent.getAction()) ) {

int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothA2dpSink.STATE_NOT_PLAYING);

BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

Log.d(LOG_TAG, String.format("ACTION_PLAYING_STATE_CHANGED state: %d", state));

if(device != null) {

if(state == BluetoothA2dpSink.STATE_PLAYING) {

Log.d(LOG_TAG, String.format("Device %s playing", device.getAddress()));

}

else if(state == BluetoothA2dpSink.STATE_NOT_PLAYING) {

Log.d(LOG_TAG, String.format("Device %s not playing", device.getAddress()));

}

}

}

else if(intent.getAction().equals(BluetoothAvrcpController.ACTION_TRACK_EVENT)) {

// Log.d(LOG_TAG, "TRACK_EVENT");

MediaMetadata metadata = intent.getParcelableExtra(BluetoothAvrcpController.EXTRA_METADATA);

// Log.v(LOG_TAG, "[Music]metadata != null) = " + (metadata != null));

if(metadata != null) {

String title = metadata.getString(MediaMetadata.METADATA_KEY_TITLE);

setMusicCoverTitle(metadata.getString(MediaMetadata.METADATA_KEY_TITLE));

// Log.v(LOG_TAG, String.format("[Music]artist: %s", artist));

// Log.v(LOG_TAG, String.format("[Music]album: %s", album));

// Log.v(LOG_TAG, String.format("[Music]duration: %s", new SimpleDateFormat("HH:mm:ss").format(duration)));

setPDuration((int)metadata.getLong(MediaMetadata.METADATA_KEY_DURATION));

}

PlaybackState playback_state = intent.getParcelableExtra(BluetoothAvrcpController.EXTRA_PLAYBACK);

// Log.v(LOG_TAG, "[Music](playback_state != null) check1 = " + (playback_state != null));

if(playback_state != null) {

int state = playback_state.getState();

// int position = (int)playback_state.getPosition();

if (state == PlaybackState.STATE_PLAYING) {

IsBTMusic_Play = true;

Log.v(LOG_TAG, "[Music]bt music is playing IsBTMusic_Play = " + IsBTMusic_Play);



if (mOnPlayStateChangedListener != null) {

if (getScreenTag() == ScreenTag.CID_MEDIA) {

mOnPlayStateChangedListener.onPlayStateChanged(ScreenTag.CID_MEDIA, Constants.PlayState.PLAYING);

} else if (getScreenTag() == ScreenTag.PID_MEDIA) {

mOnPlayStateChangedListener.onPlayStateChanged(ScreenTag.PID_MEDIA, Constants.PlayState.PLAYING);

}

}

}

else if (state == PlaybackState.STATE_PAUSED) {

IsBTMusic_Play = false;

Log.v(LOG_TAG, "[Music]bt music is pause IsBTMusic_Play = " + IsBTMusic_Play);



if (mOnPlayStateChangedListener != null) {

if (getScreenTag() == ScreenTag.CID_MEDIA) {

mOnPlayStateChangedListener.onPlayStateChanged(ScreenTag.CID_MEDIA, Constants.PlayState.PAUSE);

} else if (getScreenTag() == ScreenTag.PID_MEDIA) {

mOnPlayStateChangedListener.onPlayStateChanged(ScreenTag.PID_MEDIA, Constants.PlayState.PAUSE);

}

}

}

else if (state == PlaybackState.STATE_STOPPED) {

IsBTMusic_Play = false;

Log.v(LOG_TAG, "[Music]bt music is stop IsBTMusic_Play = " + IsBTMusic_Play);

}

// int position = (int)playback_state.getPosition();

// Log.v(LOG_TAG, "[Music]position: " + new SimpleDateFormat("HH:mm:ss").format(playback_state.getPosition()));

//Log.v(LOG_TAG, "duration = " + duration + "position = " + position);

setPPosition((int)playback_state.getPosition());

}}

else if( BluetoothAvrcpController.ACTION_PLAYER_SETTING.equals(intent.getAction()) ) {

BluetoothAvrcpPlayerSettings player_settings = intent.getParcelableExtra(BluetoothAvrcpController.EXTRA_PLAYER_SETTING);

refreshAvrcpSettings(player_settings);

}

else if(Constants.ACTION_AVRCP_CMD.equals(intent.getAction())) {

}}};



上層打通回控的程式
在media的page建立回控程式 我參考了網址:
https://github.com/PDi-Communication-Systems-Inc/lollipop-packages-apps-fsl_imx_demo/blob/master/A2dpSinkApp/java/com/freescale/a2dpsinkapp/MainActivity.java
看一下棒棒糖版本的回控 瞭解了 除了接收要註冊AVRCP相關的intent及Receiver外 傳送部分控件的建立必須先部屬BTAdapter 接著
if(mUBTAdapter == null) {
mUBTAdapter = BluetoothAdapter.getDefaultAdapter();
if(pAVRCPControllerService == null)
mUBTAdapter.getProfileProxy(mContext, mAvrcpControllerListener, BluetoothProfile.AVRCP_CONTROLLER);
else
Log.v(LOG_TAG, "pAVRCPControllerService is not null.");
}else{
Log.v(LOG_TAG, "mUBTAdapter is not null.");
if(pAVRCPControllerService == null)
mUBTAdapter.getProfileProxy(mContext, mAvrcpControllerListener, BluetoothProfile.AVRCP_CONTROLLER);
else
Log.v(LOG_TAG, "pAVRCPControllerService is not null.");

}


底層 :
Step011-05 10:27:30.251  3900  4295 I A2dpSinkStreamHandler: ecockpit mAudioManager.requestAudioFocus successful
11-05 10:27:30.251  3900  4295 D A2dpSinkStreamHandler: startAvrcpUpdates
11-05 10:27:30.251  3900  4295 I A2dpSinkStreamHandler: ecockpit startAvrcpUpdates, connected device number==0
=> packages/apps/Bluetooth/src/com/android/bluetooth/a2dpsink
startAvrcpUpdates() => avrcpService != null, but device number == 0 =>
Check avrcpService.getConnectedDevice().size();
11-05 10:27:30.251  3900  4295 I A2dpSinkStreamHandler: ecockpit mAudioManager.requestAudioFocus successful
11-05 10:27:30.251  3900  4295 D A2dpSinkStreamHandler: startAvrcpUpdates
11-05 10:27:30.251  3900  4295 I A2dpSinkStreamHandler: ecockpit startAvrcpUpdates, connected device number==0
=> packages/apps/Bluetooth/src/com/android/bluetooth/a2dpsink
startAvrcpUpdates() => avrcpService != null, but device number == 0 =>
Check avrcpService.getConnectedDevice().size();

Step1
Src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
getConnectedDevice():256
Searcg private mConnectedDevice who used.
onConnectionStateChanged():746
有打印scott log但未印出 追jni
=>packages/apps/Bluetooth/jni

剔除不需要找的function
目標鎖定在以下3cpp
./com_android_bluetooth_a2dp.cpp
./com_android_bluetooth_avrcp_controller.cpp
./com_android_bluetooth_a2dp_sink.cpp
其中Avrcp_controller與自己較相關./com_android_bluetooth_avrcp_controller.cpp


Step3 : Searching ‘btrc_ctrl_callbacks’@BT HAL
Step3 : Searching ‘init_ctrl’@BT HAL














2019年10月28日 星期一

[Android]設定開機自動啟動App與 home鍵預設讀取App 移除應用程式標籤

設定開機自動啟動App:
reference:https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/30664/
在app>java>專案目錄> 直到與MainActivity新增java class "BootBroadcastReceiver.java"如下圖 :





















新增程式碼在BootBroadcastReceiver中
import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;
public class BootBroadcastReceiver extends BroadcastReceiver {
    static final String ACTION = "android.intent.action.BOOT_COMPLETED";
    @Override    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(ACTION)) {
            Intent mainActivityIntent = new Intent(context, MainActivity.class);  // 要啟動的Activity            mainActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);            context.startActivity(mainActivityIntent);        }
    }
}

將receiver註冊在AndroidMainfest.xml內
android:name=".BootBroadcastReceiver"/>android:name=".MainActivity"    android:screenOrientation="landscape">

註冊另一action使重開機能夠自動載入:
 android:name="android.intent.action.QUICKBOOT_POWERON" /> 

設定使用者權限在AndroidMainfest.xml內
android:name="android.permission.RECEIVE_BOOT_COMPLETED">

、adb傳送BOOT_COMPLETED
我們可以通過
命令傳送BOOT_COMPLETED廣播,而不用重啟測試機或模擬器來測試BOOT_COMPLETED廣播,這條命令可以更精確的傳送到某個package,如下:

home鍵預設讀取App:
在AndroidMainfest.xml內寫入以下設定 : 
android:name="android.intent.category.LAUNCHER" />android:name="android.intent.category.HOME" />



Android移除應用程式標籤
在onCreate 呼叫hide()

if (getSupportActionBar() != null){

   getSupportActionBar().hide();

}

[Android]Camera + textureView

Camera1
縮放 :
Camera.Paramenters params = mCamera.getParameters();
params.setZoom(zoomLevel);
mCamera.setParameters(params);



Camera2
縮放
final int zoomScale = 200;
captureBuilder.set(CaptureRequest.SCALER_CROP_REGION, new
     Rect(zoomScale * mZoomLevel, zoomScale * mZoomLevel, mStartBounds.right
     - (zoomScale * mZoomLevel), mStartBounds.bottom - (zoomScale * mZoomLevel)));


TextureView解決相機預覽左右相反問題 :
mCameraTextureView.setRotationX(180.0f);




package com.example.multiscreencameratest;
import android.Manifest;import android.app.Service;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.graphics.Matrix;import android.graphics.SurfaceTexture;import android.hardware.camera2.CameraAccessException;import android.hardware.camera2.CameraCaptureSession;import android.hardware.camera2.CameraCharacteristics;import android.hardware.camera2.CameraDevice;import android.hardware.camera2.CameraManager;import android.hardware.camera2.CameraMetadata;import android.hardware.camera2.CaptureRequest;import android.hardware.camera2.params.StreamConfigurationMap;import android.media.MediaPlayer;import android.os.Bundle;
import android.app.Activity;import android.app.AlertDialog;import android.app.Presentation;import android.content.Context;import android.content.DialogInterface;import android.content.res.Resources;import android.hardware.display.DisplayManager;import android.os.Handler;import android.os.HandlerThread;import android.os.IBinder;import android.os.Message;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.util.Size;import android.util.SparseArray;import android.view.Display;import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.TextureView;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.CheckBox;import android.widget.CompoundButton;import android.widget.CompoundButton.OnCheckedChangeListener;import android.widget.AdapterView;import android.widget.AdapterView.OnItemSelectedListener;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ListView;import android.widget.Spinner;import android.widget.TextView;import android.widget.Toast;

import java.io.File;import java.io.IOException;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;
import java.util.Arrays;import java.util.HashMap;import java.util.Map;
public class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
    private final String LOG_TAG = "MultiScreenCameraTest";
    private static final int MESG_UPDATE_DISPLAY = 100;    private static final int MESG_SHOW_SCRENN = 101;    private static final int MESG_SHOW_ALL_SCRENN = 102;    private static final int MESG_HIDE_SCRENN = 103;    private static final int MESG_HIDE_ALL_SCRENN = 104;    private static final int MESG_SCAN_CAMERA = 200;
    private Context mContext = null;
    private MsgHandler mMsgHandler = null;
    private DisplayManager mDisplayManager;    private DisplayListAdapter mDisplayListAdapter;    private TextureView mCameraTextureView;
    private boolean mIsTextureViewAvailable = false;
    private CameraManager mCameraManager = null;    private CameraDevice mCameraDevice = null;    private Size mImageDimension = null;    protected CameraCaptureSession mCameraCaptureSession = null;    protected CaptureRequest.Builder mCaptureRequestBuilder = null;    private Handler mBackgroundHandler;    private HandlerThread mBackgroundThread;
    private Display[] mDisplays;    private boolean mShowAllDisplays = true;
    private HashMap, 
MultiScreen> mMultiScreenMap = null;
private HashMap, Integer> mCameraScreenMap = null; private static final int REQUEST_CAMERA_PERMISSION = 200;
private int degreeX = 0; public Document doc; public NodeList nlist;
public static int leftPillar_left; public static int leftPillar_top; public static int leftPillar_right; public static int leftPillar_bottom; public static int leftPillar_radius; public static int leftPillar_degree; public static int leftPillar_translationX; public static int leftPillar_translationY; public static float leftPillar_scaleX; public static float leftPillar_scaleY;
public static int rightPillar_left; public static int rightPillar_top; public static int rightPillar_right; public static int rightPillar_bottom; public static int rightPillar_radius; public static int rightPillar_degree; public static int rightPillar_translationX; public static int rightPillar_translationY; public static float rightPillar_scaleX; public static float rightPillar_scaleY;
public static boolean isRight = true;

private void hideSystemUI() {
View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN); }

@Override public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus); if (hasFocus) {
hideSystemUI(); }
}

@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); Log.d(LOG_TAG, "onCreate"); try {
readxml(); } catch (IOException e) {
Log.d(LOG_TAG, "XML load exception " + e); e.printStackTrace(); }
setContentView(R.layout.activity_main); mContext = getApplicationContext(); mMsgHandler = new MsgHandler();
mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE); mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); mCameraScreenMap = new HashMap, Integer>(); mCameraTextureView = (TextureView) findViewById(R.id.camera); mCameraTextureView.setSurfaceTextureListener(mTextureListener); //boris if(isRight == true){
Log.d(LOG_TAG, "[KH]isRight"); mCameraTextureView.setOutlineProvider(new TextureVideoViewOutlineProvider(0, 0, 3900, 1920, rightPillar_radius, rightPillar_degree)); //mCameraTextureView.setOutlineProvider(new TextureVideoViewOutlineProvider(rightPillar_left, rightPillar_top, rightPillar_right, rightPillar_bottom, rightPillar_radius, rightPillar_degree)); mCameraTextureView.setRotation(250);//rightPillar_degree mCameraTextureView.setTranslationX(200);//rightPillar_translationX mCameraTextureView.setTranslationY(200);//rightPillar_translationY -1000 mCameraTextureView.setScaleX(2.6f);//rightPillar_scaleX Log.d(LOG_TAG, "[KH] mCameraTextureView getWidth = " + mCameraTextureView.getWidth()); mCameraTextureView.setScaleY(2.6f);//rightPillar_scaleY //mCameraTextureView.setRotationX(180.0f); }else{
mCameraTextureView.setOutlineProvider(new TextureVideoViewOutlineProvider(leftPillar_left, leftPillar_top, leftPillar_right, leftPillar_bottom, leftPillar_radius, leftPillar_degree)); mCameraTextureView.setRotation(leftPillar_degree);//leftPillar_degree mCameraTextureView.setTranslationX(leftPillar_translationX); mCameraTextureView.setTranslationY(leftPillar_translationY); mCameraTextureView.setScaleX(leftPillar_scaleX); mCameraTextureView.setScaleY(leftPillar_scaleY); //mCameraTextureView.setRotationX(180.0f); }
mCameraTextureView.setClipToOutline(true);
mDisplayListAdapter = new DisplayListAdapter(this);

mMultiScreenMap = new HashMap, MultiScreen>();
mDisplayManager.registerDisplayListener(mDisplayListener, null); if(mMsgHandler != null) {
mMsgHandler.sendEmptyMessage(MESG_UPDATE_DISPLAY); mMsgHandler.sendEmptyMessageDelayed(MESG_SHOW_ALL_SCRENN, 1000);// mMsgHandler.sendEmptyMessageDelayed(MESG_SCAN_CAMERA, 2000); }
}

@Override protected void onResume() {
super.onResume(); Log.d(LOG_TAG, "onResume"); startBackgroundThread(); }
@Override protected void onPause() {
super.onPause(); Log.d(LOG_TAG, "onPause"); }

@Override protected void onDestroy() {
super.onDestroy(); Log.d(LOG_TAG, "onDestroy"); mDisplayManager.unregisterDisplayListener(mDisplayListener); try {
if(mCameraCaptureSession != null) {
mCameraCaptureSession.stopRepeating(); }
} catch (CameraAccessException e) {
e.printStackTrace(); }
if(mMsgHandler != null) {
mMsgHandler.sendEmptyMessage(MESG_HIDE_ALL_SCRENN); }
stopBackgroundThread(); closeCamera(); }

@Override protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); }

@Override public void onItemClick(AdapterView parent, View view, int position, long id) {
final Display display = (Display)view.getTag();// Log.d(LOG_TAG, String.format("onItemClick position: %d, DisplayId: %d", position, display.getDisplayId())); Log.d(LOG_TAG, "Show display #" + display.getDisplayId() + " info"); Context context = view.getContext(); AlertDialog.Builder builder = new AlertDialog.Builder(context); Resources r = context.getResources(); AlertDialog alert = builder
.setTitle(r.getString(
R.string.presentation_alert_info_text, display.getDisplayId()))
.setMessage(display.toString())
.setNeutralButton(R.string.presentation_alert_dismiss_text, new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog, int which) {
dialog.dismiss(); }
})
.create(); alert.show(); }

TextureView.SurfaceTextureListener mTextureListener = new TextureView.SurfaceTextureListener() {
@Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Log.d(LOG_TAG, "onSurfaceTextureAvailable"); mIsTextureViewAvailable = true; if(mMsgHandler != null) {
mMsgHandler.sendEmptyMessageDelayed(MESG_SCAN_CAMERA, 1500); }
}
@Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Transform you image captured size according to the surface width and height }
@Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
Log.d(LOG_TAG, "onSurfaceTextureDestroyed"); mIsTextureViewAvailable = false; return false; }
@Override public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private void updateDisplay() {
mDisplays = mDisplayManager.getDisplays(getDisplayCategory()); Log.d(LOG_TAG, "There are currently " + mDisplays.length + " displays connected."); mDisplayListAdapter.updateContents(); }

private String getDisplayCategory() {
return mShowAllDisplays ? null : DisplayManager.DISPLAY_CATEGORY_PRESENTATION; }

@Override public void onClick(View v) {
switch (v.getId()) {
case R.id.info:
Log.d(LOG_TAG, "Show display info"); Context context = v.getContext(); AlertDialog.Builder builder = new AlertDialog.Builder(context); final Display display = (Display)v.getTag(); Resources r = context.getResources(); AlertDialog alert = builder
.setTitle(r.getString(
R.string.presentation_alert_info_text, display.getDisplayId()))
.setMessage(display.toString())
.setNeutralButton(R.string.presentation_alert_dismiss_text, new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog, int which) {
dialog.dismiss(); }
})
.create(); alert.show(); break; default:
break; }
}

private final DisplayManager.DisplayListener mDisplayListener =
new DisplayManager.DisplayListener() {
@Override public void onDisplayAdded(int displayId) {
Log.d(LOG_TAG, "Display #" + displayId + " added"); if(mMsgHandler != null) {
mMsgHandler.sendEmptyMessage(MESG_UPDATE_DISPLAY); Message message = new Message(); message.what = MESG_SHOW_SCRENN; message.arg1 = displayId; mMsgHandler.sendMessage(message); }
}
@Override public void onDisplayChanged(int displayId) {
Log.d(LOG_TAG, "Display #" + displayId + " changed");// if(mMsgHandler != null) {// mMsgHandler.sendEmptyMessage(MESG_UPDATE_DISPLAY);// Message message = new Message();// message.what = MESG_HIDE_SCRENN;// message.arg1 = displayId;// mMsgHandler.sendMessage(message);// Message message1 = new Message();// message1.what = MESG_SHOW_SCRENN;// message1.arg1 = displayId;// mMsgHandler.sendMessage(message1);// } }
@Override public void onDisplayRemoved(int displayId) {
Log.d(LOG_TAG, "Display #" + displayId + " removed"); if(mMsgHandler != null) {
mMsgHandler.sendEmptyMessage(MESG_UPDATE_DISPLAY); Message message = new Message(); message.what = MESG_HIDE_SCRENN; message.arg1 = displayId; mMsgHandler.sendMessage(message); }
}
};
private final class DisplayListAdapter extends ArrayAdapter {
final Context mContext; public DisplayListAdapter(Context context) {
super(context, R.layout.presentation_list_item); mContext = context; }
@Override public View getView(int position, View convertView, ViewGroup parent) {
final View v; if (convertView == null) {
v = ((Activity) mContext).getLayoutInflater().inflate(
R.layout.presentation_list_item, null); } else {
v = convertView; }
final Display display = getItem(position); final int displayId = display.getDisplayId();
v.setTag(display); TextView tv = (TextView)v.findViewById(R.id.display_id); tv.setText(v.getContext().getResources().getString(
R.string.presentation_display_id_text, displayId, display.getName())); return v; }

public void updateContents() {
clear(); addAll(mDisplays); }
}

private void showScreen(Display display) {
Log.d(LOG_TAG, "Show screen on display #" + display.getDisplayId()); if(display.getDisplayId() == 0) {
Log.d(LOG_TAG, "Display id is 0, just return!"); return; }
MultiScreen screen = new MultiScreen(this, display); screen.show(); screen.setOnDismissListener(mOnDismissListener); mMultiScreenMap.put(display.getDisplayId(), screen); Log.d(LOG_TAG, "Screen count: " + mMultiScreenMap.size()); if(mMsgHandler != null) {
if(!mMsgHandler.hasMessages(MESG_SCAN_CAMERA)) {
mMsgHandler.sendEmptyMessage(MESG_SCAN_CAMERA); }
}
}

private void hideScreen(int displayId) {
Log.d(LOG_TAG, "Hide screen on display #" + displayId); if(displayId == 0) {
Log.d(LOG_TAG, "Display id is 0, just return!"); return; }
if (mMultiScreenMap.containsKey(displayId)) {
mMultiScreenMap.get(displayId).dismiss(); }
}

private final DialogInterface.OnDismissListener mOnDismissListener =
new DialogInterface.OnDismissListener() {
@Override public void onDismiss(DialogInterface dialog) {
MultiScreen presentation = (MultiScreen)dialog; int displayId = presentation.getDisplay().getDisplayId(); Log.d(LOG_TAG, "Screen on display #" + displayId + " was dismissed"); mMultiScreenMap.remove(displayId); Log.d(LOG_TAG, "Screen count: " + mMultiScreenMap.size()); if(mCameraScreenMap.containsValue(displayId)) {
for (Map.Entry,
Integer> entry : mCameraScreenMap.entrySet()) {
int display_id = entry.getValue(); if(displayId == display_id) {
mCameraScreenMap.remove(entry.getKey()); }
}
}
}
};
private void scanCamera() {
Log.d(LOG_TAG, "scanCamera"); try {
for (String camera_id : mCameraManager.getCameraIdList()) {
Log.d(LOG_TAG, String.format("camera_id: %s", camera_id)); if(camera_id.equals("0")) {
mCameraScreenMap.put(camera_id, 0); openCamera(camera_id); }
if(!mCameraScreenMap.containsKey(camera_id)) {
for (Map.Entry, MultiScreen> entry : mMultiScreenMap.entrySet()) {
int display_id = entry.getKey(); if(!mCameraScreenMap.containsValue(display_id)) {
mCameraScreenMap.put(camera_id, display_id); mMultiScreenMap.get(display_id).openCamera(camera_id); }
}
}
}
} catch (CameraAccessException e) {
e.printStackTrace(); }
}

public void openCamera(String camera_id) {
Log.d(LOG_TAG, String.format("openCamera camera_id: %s", camera_id)); try {
CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(camera_id); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); Size size[] = map.getOutputSizes(SurfaceTexture.class); for(int index = 0; index < size.length; ++index) {
Log.d(LOG_TAG, "index: " + index + ", size: " + size[index].getWidth() + "x" + size[index].getHeight()); }
mImageDimension = map.getOutputSizes(SurfaceTexture.class)[0]; Log.d(LOG_TAG, String.format("Image dimension width: %d, height: %d", mImageDimension.getWidth(), mImageDimension.getHeight())); // Add permission for camera and let user grant the permission if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION); return; }
mCameraManager.openCamera(camera_id, mStateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace(); }
}

private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override public void onOpened(CameraDevice camera) {
//This is called when the camera is open Log.d(LOG_TAG, "onOpened id: " + camera.getId()); mCameraDevice = camera; createCameraPreview(); }
@Override public void onDisconnected(CameraDevice camera) {
Log.d(LOG_TAG, "onDisconnected id: " + camera.getId()); if(mCameraDevice != null) {
mCameraDevice.close(); }
}
@Override public void onError(CameraDevice camera, int error) {
Log.d(LOG_TAG, "onError id: " + camera.getId() + " error: " + error); if(mCameraDevice != null) {
mCameraDevice.close(); }
}
};
private void createCameraPreview() {
Log.d(LOG_TAG, "createCameraPreview"); try {
SurfaceTexture texture = mCameraTextureView.getSurfaceTexture(); texture.setDefaultBufferSize(mImageDimension.getWidth(), mImageDimension.getHeight()); Surface surface = new Surface(texture); mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mCaptureRequestBuilder.addTarget(surface); mCameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback(){
@Override public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
//The camera is already closed if (null == mCameraDevice) {
return; }
mCameraCaptureSession = cameraCaptureSession; mCaptureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); updatePreview(); }
@Override public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(mContext, "Configuration change", Toast.LENGTH_SHORT).show(); }
}, null); } catch (CameraAccessException e) {
e.printStackTrace(); }
}

protected void updatePreview() {
Log.d(LOG_TAG, String.format("updatePreview")); try {
if(mCameraCaptureSession != null) {
mCameraCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(), null, mBackgroundHandler); }
else {
Log.d(LOG_TAG, "No camera capture session"); }
} catch (CameraAccessException e) {
e.printStackTrace(); }
}

private void closeCamera() {
if(mCameraDevice != null) {
mCameraDevice.close(); }
}

private void startBackgroundThread() {
Log.d(LOG_TAG, "startBackgroundThread"); mBackgroundThread = new HandlerThread("Camera Background"); mBackgroundThread.start(); mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); }

public void readxml()throws IOException{
Log.d(LOG_TAG, "[KH]enterning readxml"); File f = new File("/sdcard/Download/cam_setting.xml"); if (f.exists()){
Log.d(LOG_TAG, "[KH]xml setting file is exist"); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); System.out.println(dbf.getClass().getName()); try {
DocumentBuilder db=dbf.newDocumentBuilder(); doc=db.parse(new File("/sdcard/Download/cam_setting.xml")); nlist=doc.getElementsByTagName("cam_configs"); int len=nlist.getLength(); for(int i=0;i;i++)
{
Element eltPer=(Element)nlist.item(i); Node elleftPillar_left = eltPer.getElementsByTagName("leftPillar_left").item(0); Node elleftPillar_top = eltPer.getElementsByTagName("leftPillar_top").item(0); Node elleftPillar_right = eltPer.getElementsByTagName("leftPillar_right").item(0); Node elleftPillar_bottom = eltPer.getElementsByTagName("leftPillar_bottom").item(0); Node elleftPillar_radius = eltPer.getElementsByTagName("leftPillar_radius").item(0); Node elleftPillar_degree = eltPer.getElementsByTagName("leftPillar_degree").item(0); Node elleftPillar_translationX = eltPer.getElementsByTagName("leftPillar_translationX").item(0); Node elleftPillar_translationY = eltPer.getElementsByTagName("leftPillar_translationY").item(0); Node elleftPillar_scaleX = eltPer.getElementsByTagName("leftPillar_scaleX").item(0); Node elleftPillar_scaleY = eltPer.getElementsByTagName("leftPillar_scaleY").item(0);
Node elrightPillar_left = eltPer.getElementsByTagName("rightPillar_left").item(0); Node elrightPillar_top = eltPer.getElementsByTagName("rightPillar_top").item(0); Node elrightPillar_right = eltPer.getElementsByTagName("rightPillar_right").item(0); Node elrightPillar_bottom = eltPer.getElementsByTagName("rightPillar_bottom").item(0); Node elrightPillar_radius = eltPer.getElementsByTagName("rightPillar_radius").item(0); Node elrightPillar_degree = eltPer.getElementsByTagName("rightPillar_degree").item(0); Node elrightPillar_translationX = eltPer.getElementsByTagName("rightPillar_translationX").item(0); Node elrightPillar_translationY = eltPer.getElementsByTagName("rightPillar_translationY").item(0); Node elrightPillar_scaleX = eltPer.getElementsByTagName("rightPillar_scaleX").item(0); Node elrightPillar_scaleY = eltPer.getElementsByTagName("rightPillar_scaleY").item(0);
leftPillar_left = Integer.valueOf(elleftPillar_left.getFirstChild().getNodeValue()).intValue(); leftPillar_top = Integer.valueOf(elleftPillar_top.getFirstChild().getNodeValue()).intValue(); leftPillar_right = Integer.valueOf(elleftPillar_right.getFirstChild().getNodeValue()).intValue(); leftPillar_bottom = Integer.valueOf(elleftPillar_bottom.getFirstChild().getNodeValue()).intValue(); leftPillar_radius = Integer.valueOf(elleftPillar_radius.getFirstChild().getNodeValue()).intValue(); leftPillar_degree = Integer.valueOf(elleftPillar_degree.getFirstChild().getNodeValue()).intValue(); leftPillar_translationX = Integer.valueOf(elleftPillar_translationX.getFirstChild().getNodeValue()).intValue(); leftPillar_translationY = Integer.valueOf(elleftPillar_translationY.getFirstChild().getNodeValue()).intValue(); leftPillar_scaleX = Float.valueOf(elleftPillar_scaleX.getFirstChild().getNodeValue()).floatValue(); leftPillar_scaleY = Float.valueOf(elleftPillar_scaleY.getFirstChild().getNodeValue()).floatValue();
rightPillar_left = Integer.valueOf(elrightPillar_left.getFirstChild().getNodeValue()).intValue(); rightPillar_top = Integer.valueOf(elrightPillar_top.getFirstChild().getNodeValue()).intValue(); rightPillar_right = Integer.valueOf(elrightPillar_right.getFirstChild().getNodeValue()).intValue(); rightPillar_bottom = Integer.valueOf(elrightPillar_bottom.getFirstChild().getNodeValue()).intValue(); rightPillar_radius = Integer.valueOf(elrightPillar_radius.getFirstChild().getNodeValue()).intValue(); rightPillar_degree = Integer.valueOf(elrightPillar_degree.getFirstChild().getNodeValue()).intValue(); rightPillar_translationX = Integer.valueOf(elrightPillar_translationX.getFirstChild().getNodeValue()).intValue(); rightPillar_translationY = Integer.valueOf(elrightPillar_translationY.getFirstChild().getNodeValue()).intValue(); rightPillar_scaleX = Float.valueOf(elrightPillar_scaleX.getFirstChild().getNodeValue()).floatValue(); rightPillar_scaleY = Float.valueOf(elrightPillar_scaleY.getFirstChild().getNodeValue()).floatValue(); Log.d(LOG_TAG, "leftPillar_left = " + leftPillar_left + ",leftPillar_top = " + leftPillar_top + ",leftPillar_right = " + leftPillar_right +
",leftPillar_bottom = " + leftPillar_bottom + ",leftPillar_radius = " + leftPillar_radius + ",leftPillar_degree = " + leftPillar_degree +
",leftPillar_translationX = " + leftPillar_translationX + ",leftPillar_translationY = " + leftPillar_translationY +
",leftPillar_scaleX = " + leftPillar_scaleX + ", leftPillar_scaleY = " + leftPillar_scaleY +
",rightPillar_left = " + rightPillar_left + ",rightPillar_top = " + rightPillar_top + ",rightPillar_right = " + rightPillar_right +
",rightPillar_bottom = " + rightPillar_bottom + ",rightPillar_radius = " + rightPillar_radius + ",rightPillar_degree = " + rightPillar_degree +
",rightPillar_translationX = " + rightPillar_translationX + ",rightPillar_translationY = " + rightPillar_translationY +
",rightPillar_scaleX = " + rightPillar_scaleX + ",rightPillar_scaleY = " + rightPillar_scaleY); }
} catch (Exception e) {
Log.e(LOG_TAG, "file load exception " + e); }
}else{
Log.d(LOG_TAG, "The xml file is not exist"); leftPillar_left = 0; leftPillar_top = 120; leftPillar_right = 1600; leftPillar_bottom = 780; leftPillar_radius = 0; leftPillar_degree = -20; leftPillar_translationX = -500; leftPillar_translationY = -500; leftPillar_scaleX = 1.0f; leftPillar_scaleY = 1.0f; rightPillar_left = 0; rightPillar_top = 120; rightPillar_right = 1600; rightPillar_bottom = 780; rightPillar_radius = 0; rightPillar_degree = -20; rightPillar_translationX = -500; rightPillar_translationY = -500; rightPillar_scaleX = 1.0f; rightPillar_scaleY = 1.0f; }
}

private void stopBackgroundThread() {
Log.d(LOG_TAG, "stopBackgroundThread"); mBackgroundThread.quitSafely(); try {
mBackgroundThread.join(); mBackgroundThread = null; mBackgroundHandler = null; } catch (InterruptedException e) {
e.printStackTrace(); }
}

private final class MsgHandler extends Handler
{
@Override public void handleMessage(Message msg)
{
Log.d(LOG_TAG, "handler message = " + msg.what);
switch (msg.what) {
case MESG_UPDATE_DISPLAY:
Log.d(LOG_TAG, "MESG_UPDATE_DISPLAY"); updateDisplay(); break; case MESG_SHOW_ALL_SCRENN:
Log.d(LOG_TAG, "MESG_SHOW_ALL_SCRENN"); for (Display display : mDisplays) {
// Log.d(LOG_TAG, "" + display); showScreen(display); }
break; case MESG_SHOW_SCRENN:
Log.d(LOG_TAG, "MESG_SHOW_SCRENN"); for (Display display : mDisplays) {
//Log.d(LOG_TAG, "" + display); if(display.getDisplayId() == msg.arg1) {
showScreen(display); break; }
}
break; case MESG_HIDE_SCRENN:
Log.d(LOG_TAG, "MESG_HIDE_SCRENN"); hideScreen(msg.arg1); break; case MESG_HIDE_ALL_SCRENN:
Log.d(LOG_TAG, "MESG_HIDE_ALL_SCRENN"); for (Display display : mDisplays) {
// Log.d(LOG_TAG, "" + display); hideScreen(display.getDisplayId()); }
break; case MESG_SCAN_CAMERA:
Log.d(LOG_TAG, "MESG_SCAN_CAMERA"); scanCamera(); break; default:
Log.d(LOG_TAG, "unknown message header " + msg.what); break; }
}
}
}