From ba42b72744f6749e079ba7dbe19206ff7275f840 Mon Sep 17 00:00:00 2001 From: Matthew Date: Thu, 15 May 2025 10:14:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96938=E7=BD=91=E7=BB=9C?= =?UTF-8?q?=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/cpp/PhoneDevice.cpp | 20 +- .../com/xypower/mpapp/MicroPhotoService.java | 260 +++++++++++++----- 2 files changed, 207 insertions(+), 73 deletions(-) diff --git a/app/src/main/cpp/PhoneDevice.cpp b/app/src/main/cpp/PhoneDevice.cpp index 1f8585f7..83537df7 100644 --- a/app/src/main/cpp/PhoneDevice.cpp +++ b/app/src/main/cpp/PhoneDevice.cpp @@ -48,6 +48,12 @@ #include namespace fs = std::filesystem; +#ifdef NDEBUG +#define MAX_NETCAMERA_RETRIES 128 +#else +#define MAX_NETCAMERA_RETRIES 32 +#endif + extern bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread); bool makeHdr(vector& times, std::vector& paths, cv::Mat& rgb) @@ -1604,7 +1610,9 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c std::shared_ptr ethernetPowerCtrl = std::make_shared(localPhotoInfo.closeDelayTime); std::this_thread::sleep_for(std::chrono::milliseconds(5000)); + net_handle_t netHandle = 0; +#ifndef USING_N938 // Wait about 10s for (int idx = 0; idx < 84; idx++) { @@ -1664,6 +1672,7 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c #endif XYLOG(XYLOG_SEVERITY_INFO, "Ethernet is Available Handle=%llu CH=%u PR=%X PHOTOID=%u", (uint64_t)netHandle, (uint32_t)localPhotoInfo.channel, (uint32_t)localPhotoInfo.preset, localPhotoInfo.photoId); } +#endif // USING_N938 // if (mBuildTime < 1738166400) { @@ -1693,7 +1702,7 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c std::string lastError; int idx = 0; vendorCtrl->SetResolution(localPhotoInfo.channel, localPhotoInfo.cameraId, localPhotoInfo.width, localPhotoInfo.height); - for (; idx < 128; idx++) + for (; idx < MAX_NETCAMERA_RETRIES; idx++) { netHandle = GetEthnetHandle(); vendorCtrl->UpdateNetHandle(netHandle); @@ -1782,13 +1791,8 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c } else { - XYLOG(XYLOG_SEVERITY_ERROR, "Failed to TP on NET Camera CH=%u PR=%X PHOTOID=%u Retries=%d URL=http://%s%s, LastErr:%s", (uint32_t)localPhotoInfo.channel, (uint32_t)localPhotoInfo.preset, - localPhotoInfo.photoId, idx, netPhotoInfo.ip, netPhotoInfo.url, lastError.c_str()); -#if !defined(NDEBUG) && defined(OUTPUT_DBG_INFO) - std::string pwrStatus = powerCtrlPtr->GetStatus(); - pwrStatus += ethernetPowerCtrl->GetStatus(); - XYLOG(XYLOG_SEVERITY_ERROR, "Failed to TP on NET Camera PWR:%s", pwrStatus.c_str()); -#endif + XYLOG(XYLOG_SEVERITY_ERROR, "Failed to TP on NET Camera CH=%u PR=%X PHOTOID=%u Retries=%d LastErr:%s", + (uint32_t)localPhotoInfo.channel, (uint32_t)localPhotoInfo.preset, localPhotoInfo.photoId, idx, lastError.c_str()); TakePhotoCb(0, localPhotoInfo, "", 0); } diff --git a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java index 718fbeea..0b8bea4b 100644 --- a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java +++ b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java @@ -20,6 +20,10 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.ImageDecoder; import android.graphics.Matrix; +import android.hardware.usb.UsbConstants; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbInterface; +import android.hardware.usb.UsbManager; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; @@ -304,6 +308,13 @@ public class MicroPhotoService extends Service { intentFilter.addAction(ACTION_GPS_TIMEOUT); intentFilter.addAction(ACTION_RESTART); intentFilter.addAction(Intent.ACTION_TIME_CHANGED); + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) { + if (usingEthernet()) { + intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); + intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); + } + } getApplicationContext().registerReceiver(mAlarmReceiver, intentFilter, Context.RECEIVER_EXPORTED | Context.RECEIVER_VISIBLE_TO_INSTANT_APPS); } { @@ -747,7 +758,47 @@ public class MicroPhotoService extends Service { Date date = new Date(); long startTime = (date.getTime() + 999) / 1000; mService.updateCaptureSchedule(startTime); + } else if (TextUtils.equals(ConnectivityManager.CONNECTIVITY_ACTION, action)) { + // mService.onNetworkChanged(intent); + } else if (TextUtils.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED, action)) { + UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + if (isEthernetAdapter(device)) { + // 尝试设置以太网IP + // mService.onNetworkChanged(intent); + } + } else if (TextUtils.equals(UsbManager.ACTION_USB_DEVICE_DETACHED, action)) { + + } + } + + private boolean isEthernetAdapter(UsbDevice device) { + // 根据设备VID/PID或类型判断是否为以太网适配器 + // 例如常见的以太网适配器类型为USB Class 0x02 (Communications) 或 0x0a (CDC Data) + int usbDevClass = device.getDeviceClass(); + if (usbDevClass == UsbConstants.USB_CLASS_COMM || + usbDevClass == UsbConstants.USB_CLASS_CDC_DATA) { + return true; + } + + int interfaceCount = device.getInterfaceCount(); + for (int i = 0; i < interfaceCount; i++) { + UsbInterface usbInterface = device.getInterface(i); + + // CDC通讯类 (0x02)或CDC数据类 + if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_COMM || + usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA) { + return true; + } + + // 特定CDC-ECM/NCM子类判断 + if (usbInterface.getInterfaceClass() == 0x02 && + (usbInterface.getInterfaceSubclass() == 0x06 || // ECM + usbInterface.getInterfaceSubclass() == 0x0D)) { // NCM + return true; + } } + + return false; } } @@ -1067,6 +1118,122 @@ public class MicroPhotoService extends Service { return defaultNetHandle; } + protected void onNetworkChanged(final Intent intent) { + try { + new Thread(new Runnable() { + @Override + public void run() { + for (int idx = 0; idx < 8; idx++) { + if (checkNetworkInterfaces("eth0")) { + break; + } + sleep(40); + } + setStaticNetwork("eth0", "192.168.68.91", "192.168.68.91", "192.168.68.0", 24); + } + + private boolean checkNetworkInterfaces(String iface) { + Network[] networks = mConnectivityManager.getAllNetworks(); + + for (Network network : networks) { + LinkProperties lp = mConnectivityManager.getLinkProperties(network); + if (lp != null) { + if (TextUtils.equals(iface, lp.getInterfaceName())) { + return true; + } + } + } + + return false; + } + + }).start(); + + + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + protected class EhternetCallback extends ConnectivityManager.NetworkCallback { + @Override + public void onLost(Network network) { + infoLog("Network Lost " + network.toString()); + updateEhernet(mNativeHandle, network.getNetworkHandle(), false); + updateDefaultNetwork(); + } + @Override + public void onAvailable(final Network network) { + String ip = ""; + try { + NetworkInfo ni = mConnectivityManager.getNetworkInfo(network); + LinkProperties lp = mConnectivityManager.getLinkProperties(network); + if (lp != null) { + + final String iface = lp.getInterfaceName(); + new Thread(new Runnable() { + @Override + public void run() { + if (getCustomAppId() == 2) { + // setStaticNetwork(iface, "192.168.68.91", "192.168.68.91", "192.168.68.0", 24); + } else { + setEthernetRoute(iface, "192.168.68.0", 24); + } + } + }).start(); + + List addresses = lp.getLinkAddresses(); + if (addresses != null && addresses.size() > 0) { + for (LinkAddress linkAddress : addresses) { + InetAddress inetAddress = linkAddress.getAddress(); + if (inetAddress != null && inetAddress instanceof Inet4Address) { + ip = inetAddress.getHostAddress(); + break; + } + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + + infoLog("Network Available " + network.toString() + " IP=" + ip + " Handle=" + Long.toString(network.getNetworkHandle())); + updateEhernet(mNativeHandle, network.getNetworkHandle(), true); + updateDefaultNetwork(); + } + + private void updateDefaultNetwork() { + MicroPhotoService thisService = MicroPhotoService.this; + long defaultNetHandle = thisService.getDefaultNetworkHandle(); + if (defaultNetHandle != 0) { + thisService.updateActiveNetwork(thisService.mNativeHandle, defaultNetHandle, true); + } + } + + @Override + public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { + String interfaceName = linkProperties.getInterfaceName(); + if (interfaceName != null && + (interfaceName.startsWith("eth") || + interfaceName.startsWith("usb") || + interfaceName.startsWith("rndis"))) { + // 检测到以太网接口,可以尝试设置 IP + // configureEthernetIp(interfaceName); + + Log.d("onLinkPropertiesChanged", "Ethernet hardware detected"); + } + } + + @Override + public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { + // 检查是否是以太网,即使没有完整的网络功能 + if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { + // 以太网硬件检测到 + Log.d("EthernetMonitor", "Ethernet hardware detected"); + } + } + } + private void startTerminalService(Intent intent) { if (MicroPhotoService.this.mNativeHandle != 0) { @@ -1135,63 +1302,9 @@ public class MicroPhotoService extends Service { try { if (usingEthernet()) { - mNetworkCallback = new ConnectivityManager.NetworkCallback() { - @Override - public void onLost(Network network) { - infoLog("Network Lost " + network.toString()); - updateEhernet(mNativeHandle, network.getNetworkHandle(), false); - updateDefaultNetwork(); - } - @Override - public void onAvailable(final Network network) { - String ip = ""; - try { - NetworkInfo ni = mConnectivityManager.getNetworkInfo(network); - LinkProperties lp = mConnectivityManager.getLinkProperties(network); - if (lp != null) { - - final String iface = lp.getInterfaceName(); - new Thread(new Runnable() { - @Override - public void run() { - if (getCustomAppId() == 2) { - setStaticNetwork(iface, "192.168.68.91", "192.168.68.91", "192.168.68.0", 24); - } else { - setEthernetRoute(iface, "192.168.68.0", 24); - } - } - }).start(); - - List addresses = lp.getLinkAddresses(); - if (addresses != null && addresses.size() > 0) { - for (LinkAddress linkAddress : addresses) { - InetAddress inetAddress = linkAddress.getAddress(); - if (inetAddress != null && inetAddress instanceof Inet4Address) { - ip = inetAddress.getHostAddress(); - break; - } - } - } - } - } catch (Exception ex) { - ex.printStackTrace(); - } - - infoLog("Network Available " + network.toString() + " IP=" + ip + " Handle=" + Long.toString(network.getNetworkHandle())); - updateEhernet(mNativeHandle, network.getNetworkHandle(), true); - updateDefaultNetwork(); - } - - private void updateDefaultNetwork() { - MicroPhotoService thisService = MicroPhotoService.this; - long defaultNetHandle = thisService.getDefaultNetworkHandle(); - if (defaultNetHandle != 0) { - thisService.updateActiveNetwork(thisService.mNativeHandle, defaultNetHandle, true); - } - } - }; - + mNetworkCallback = new EhternetCallback(); NetworkRequest request = new NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .build(); @@ -1570,7 +1683,6 @@ public class MicroPhotoService extends Service { try { Process process = Runtime.getRuntime().exec("/system/xbin/su root"); DataOutputStream os = new DataOutputStream(process.getOutputStream()); - os.writeBytes("/system/bin/reboot\n"); os.writeBytes("exit\n"); // 重要:退出su shell os.flush(); @@ -1684,8 +1796,17 @@ public class MicroPhotoService extends Service { return exitCode; } - public void setStaticNetwork(String iface, String ip, String netmask, String gateway) + public void setStaticNetwork(final String iface, final String ip, final String netmask, final String gateway) { + if (getCustomAppId() == 2) { + // N938 + new Thread(new Runnable() { + @Override + public void run() { + setStaticNetwork(iface, ip, gateway, "192.168.68.0", 24); + } + }).start(); + } if (!TextUtils.equals("0.0.0.0", ip)) { if (false) { @@ -1801,9 +1922,9 @@ public class MicroPhotoService extends Service { Process process = Runtime.getRuntime().exec("/system/xbin/su root"); DataOutputStream os = new DataOutputStream(process.getOutputStream()); - os.writeBytes("/system/bin/ip link set eth0 down"); - os.writeBytes("/system/bin/ip addr add 192.168.68.91/24 dev eth0"); - os.writeBytes("/system/bin/ip link set eth0 up"); + // os.writeBytes("/system/bin/ip link set eth0 down\n"); + os.writeBytes("/system/bin/ip addr add 192.168.68.91/24 broadcast 192.168.68.255 dev eth0\n"); + // os.writeBytes("/system/bin/ip link set eth0 up\n"); // os.writeBytes("/system/bin/ip route delete 192.168.68.0/24 table 20 2>/dev/null || true\n"); os.writeBytes("/system/bin/ip route replace 192.168.68.0/24 dev eth0 proto static scope link table 20\n"); os.writeBytes("/system/bin/ip route flush cache\n"); @@ -1817,6 +1938,16 @@ public class MicroPhotoService extends Service { if (exitValue != 0) { } + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String line = null; + StringBuilder error = new StringBuilder(); + while ((line = reader.readLine()) != null) { + error.append(line); + error.append("\n"); + } + + Log.e(TAG, error.toString()); + sleep(100); for (int idx = 0; idx < 10; idx++) { Process routeProcess3 = Runtime.getRuntime().exec("/system/xbin/su root"); @@ -1830,10 +1961,9 @@ public class MicroPhotoService extends Service { os3.flush(); int commandExitCode = -1; - BufferedReader reader = new BufferedReader(new InputStreamReader(routeProcess3.getErrorStream())); - String line; - StringBuilder error = new StringBuilder(); - while ((line = reader.readLine()) != null) { + BufferedReader reader2 = new BufferedReader(new InputStreamReader(routeProcess3.getErrorStream())); + StringBuilder error2 = new StringBuilder(); + while ((line = reader2.readLine()) != null) { if (line.startsWith("CMD_RESULT:")) { commandExitCode = Integer.parseInt(line.substring(11)); Log.d("RouteConfig", "Command exit code: " + commandExitCode);