【干货】Android系统定制基础篇:第八部分(增加以太网设置菜单、支持多摄像头、替换默认签名)

一、增加以太网设置菜单

Android 系统设置默认并没有以太网相关设置项,但以太网功能是支持的,因此我们仅仅需要增加设置界面即可。以太网设置界面如下:
在这里插入图片描述
修改

diff --git a/packages/apps/Settings/AndroidManifest.xml b/packages/apps/Settings/AndroidManifest.xml
old mode 100644
new mode 100755
index b216bc5..85b1fd9
--- a/packages/apps/Settings/AndroidManifest.xml
+++ b/packages/apps/Settings/AndroidManifest.xml
@@ -479,6 +479,30 @@
                 android:value="com.android.settings.TetherSettings" />
         </activity-alias>
 
+        <activity android:name="Settings$EthernetSettingsActivity"
+                android:label="@string/ethernet_settings_title"
+                android:icon="@drawable/ic_settings_wireless"
+                android:taskAffinity="">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.VOICE_LAUNCH" />
+                <category android:name="com.android.settings.SHORTCUT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.EthernetSettings" />
+        </activity>
+        
+        <!-- Keep compatibility with old shortcuts. -->
+         <activity-alias android:name=".EthernetSettings"
+                android:label="@string/ethernet_settings"
+                android:clearTaskOnLaunch="true"
+                android:targetActivity="Settings$EthernetSettingsActivity"
+                android:exported="true">
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.EthernetSettings" />
+         </activity-alias>
+
         <activity android:name="Settings$WifiP2pSettingsActivity"
                 android:taskAffinity="com.android.settings"
                 android:parentActivityName="Settings$WifiSettingsActivity">
diff --git a/packages/apps/Settings/res/drawable/ic_ethernet.xml b/packages/apps/Settings/res/drawable/ic_ethernet.xml
new file mode 100755
index 0000000..25a2438
--- /dev/null
+++ b/packages/apps/Settings/res/drawable/ic_ethernet.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2016 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M7.77,6.76L6.23,5.48 0.82,12l5.41,6.52 1.54,-1.28L3.42,12l4.35,-5.24zM7,13h2v-2L7,11v2zM17,11h-2v2h2v-2zM11,13h2v-2h-2v2zM17.77,5.48l-1.54,1.28L20.58,12l-4.35,5.24 1.54,1.28L23.18,12l-5.41,-6.52z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/apps/Settings/res/layout/static_ip_dialog.xml b/packages/apps/Settings/res/layout/static_ip_dialog.xml
new file mode 100755
index 0000000..5623a05
--- /dev/null
+++ b/packages/apps/Settings/res/layout/static_ip_dialog.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+     Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:fadeScrollbars="false">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:paddingBottom="8dip">
+
+        <LinearLayout
+            android:id="@+id/wifi_advanced_fields"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:id="@+id/proxy_fields"
+                style="@style/wifi_section"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <LinearLayout
+                    android:id="@+id/static_ip"
+                    style="@style/wifi_section"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content">
+
+                    <LinearLayout
+                        style="@style/wifi_item"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content">
+
+                        <TextView
+                            style="@style/wifi_item_label"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/ethernet_ip_addr" />
+
+                        <EditText
+                            android:id="@+id/edt_ip"
+                            style="@style/wifi_item_edit_content"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:hint="@string/ethernet_ip_hint"
+                            android:inputType="textNoSuggestions"
+                            android:singleLine="true" />
+                    </LinearLayout>
+
+                    <LinearLayout
+                        style="@style/wifi_item"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content">
+
+                        <TextView
+                            style="@style/wifi_item_label"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/ethernet_gateway" />
+
+                        <EditText
+                            android:id="@+id/edt_gateway"
+                            style="@style/wifi_item_edit_content"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:hint="@string/ethernet_gateway_hint"
+                            android:inputType="textNoSuggestions"
+                            android:singleLine="true" />
+                    </LinearLayout>
+
+                    <LinearLayout
+                        style="@style/wifi_item"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content">
+
+                        <TextView
+                            style="@style/wifi_item_label"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/ethernet_netmask" />
+
+                        <EditText
+                            android:id="@+id/edt_netmask"
+                            style="@style/wifi_item_edit_content"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:hint="@string/ethernet_netmask_hint"
+                            android:inputType="textNoSuggestions"
+                            android:singleLine="true" />
+                    </LinearLayout>
+
+                    <LinearLayout
+                        style="@style/wifi_item"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content">
+
+                        <TextView
+                            style="@style/wifi_item_label"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/ethernet_dns1" />
+
+                        <EditText
+                            android:id="@+id/edt_dns1"
+                            style="@style/wifi_item_edit_content"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:hint="@string/ethernet_dns1_hint"
+                            android:inputType="textNoSuggestions"
+                            android:singleLine="true" />
+                    </LinearLayout>
+
+                    <LinearLayout
+                        style="@style/wifi_item"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content">
+
+                        <TextView
+                            style="@style/wifi_item_label"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/ethernet_dns2" />
+
+                        <EditText
+                            android:id="@+id/edt_dns2"
+                            style="@style/wifi_item_edit_content"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:hint="@string/ethernet_dns2_hint"
+                            android:inputType="textNoSuggestions"
+                            android:singleLine="true" />
+                    </LinearLayout>
+                </LinearLayout>
+            </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/packages/apps/Settings/res/values-en-rGB/strings.xml b/packages/apps/Settings/res/values-en-rGB/strings.xml
old mode 100644
new mode 100755
index 54dcc39..389d059
--- a/packages/apps/Settings/res/values-en-rGB/strings.xml
+++ b/packages/apps/Settings/res/values-en-rGB/strings.xml
@@ -1346,7 +1346,8 @@
     <string name="reset_network_confirm_title" msgid="1759888886976962773">"Reset?"</string>
     <string name="network_reset_not_available" msgid="7188610385577164676">"Network reset is not available for this user"</string>
     <string name="reset_network_complete_toast" msgid="787829973559541880">"Network settings have been reset"</string>
     <string name="master_clear_title" msgid="3531267871084279512">"Erase all data (factory reset)"</string>
+    <string name="ethernet_settings_title">"Ehernet"</string>
     <string name="master_clear_desc" product="tablet" msgid="9146059417023157222">"This will erase all data from your tablet\'s "<b>"internal storage"</b>", including:\n\n"<li>"Your Google account"</li>\n<li>"System and app data and settings"</li>\n<li>"Downloaded apps"</li></string>
     <string name="master_clear_desc" product="default" msgid="4800386183314202571">"This will erase all data from your phone\'s "<b>"internal storage"</b>", including:\n\n"<li>"Your Google account"</li>\n<li>"System and app data and settings"</li>\n<li>"Downloaded apps"</li></string>
     <string name="master_clear_accounts" product="default" msgid="6412857499147999073">\n\n"You are currently signed in to the following accounts:\n"</string>
diff --git a/packages/apps/Settings/res/values-en-rIN/strings.xml b/packages/apps/Settings/res/values-en-rIN/strings.xml
old mode 100644
new mode 100755
index 54dcc39..389d059
--- a/packages/apps/Settings/res/values-en-rIN/strings.xml
+++ b/packages/apps/Settings/res/values-en-rIN/strings.xml
@@ -1346,7 +1346,8 @@
     <string name="reset_network_confirm_title" msgid="1759888886976962773">"Reset?"</string>
     <string name="network_reset_not_available" msgid="7188610385577164676">"Network reset is not available for this user"</string>
     <string name="reset_network_complete_toast" msgid="787829973559541880">"Network settings have been reset"</string>
     <string name="master_clear_title" msgid="3531267871084279512">"Erase all data (factory reset)"</string>
+    <string name="ethernet_settings_title">"Ehernet"</string>
     <string name="master_clear_desc" product="tablet" msgid="9146059417023157222">"This will erase all data from your tablet\'s "<b>"internal storage"</b>", including:\n\n"<li>"Your Google account"</li>\n<li>"System and app data and settings"</li>\n<li>"Downloaded apps"</li></string>
     <string name="master_clear_desc" product="default" msgid="4800386183314202571">"This will erase all data from your phone\'s "<b>"internal storage"</b>", including:\n\n"<li>"Your Google account"</li>\n<li>"System and app data and settings"</li>\n<li>"Downloaded apps"</li></string>
     <string name="master_clear_accounts" product="default" msgid="6412857499147999073">\n\n"You are currently signed in to the following accounts:\n"</string>
diff --git a/packages/apps/Settings/res/values/arrays.xml b/packages/apps/Settings/res/values/arrays.xml
old mode 100644
new mode 100755
index 8ead532..2be86f0
--- a/packages/apps/Settings/res/values/arrays.xml
+++ b/packages/apps/Settings/res/values/arrays.xml
@@ -1070,4 +1115,14 @@
         <item>sdcard</item>
         <item>usb</item>
     </string-array>
+
+    <!--ethernet mode select -->    
+    <string-array name="ethernet_mode_location">
+        <item>@string/ethernet_static</item>
+        <item>@string/ethernet_dhcp</item>
+    </string-array>
+    <string-array name="ethernet_mode_values">
+        <item>StaticIP</item>
+        <item>DHCP</item>
+    </string-array>
 </resources>
diff --git a/packages/apps/Settings/res/values/strings.xml b/packages/apps/Settings/res/values/strings.xml
old mode 100644
new mode 100755
index 0f95516..f8c1741
--- a/packages/apps/Settings/res/values/strings.xml
+++ b/packages/apps/Settings/res/values/strings.xml
@@ -2386,8 +2386,10 @@
     <string name="accelerometer_summary_off" product="default">Switch orientation automatically when rotating phone</string>
     <!-- Sound & display settings screen, setting option name to change brightness level -->
     <string name="brightness">Brightness level</string>
     <string name="brightness_ext">Extern Brightness level</string>
     <!-- Sound & display settings screen, setting option name to change brightness level [CHAR LIMIT=30] -->
     <string name="brightness_title">Brightness</string>
     <string name="brightness_ext_title">Extern Brightness</string>
     <!-- Sound & display settings screen, setting option summary to change brightness level -->
     <string name="brightness_summary">Adjust the brightness of the screen</string>
     <!-- Sound & display settings screen, setting option name to enable adaptive brightness [CHAR LIMIT=30] -->
@@ -2639,6 +2641,9 @@
     <string name="build_number">Build number</string>
     <!-- About phone screen,  setting option name  [CHAR LIMIT=40] -->
     <string name="selinux_status">SELinux status</string>
     <string name="tb_firmware_version">Firmware version</string>
     <string name="tb_rom_version">ROM version</string>
     <string name="tb_hardware_version">Hardware version</string>
 
     <!-- About phone screen, show when a value of some status item is unavailable. -->
     <string name="device_info_not_available">Not available</string>
@@ -3156,6 +3161,29 @@
     <!-- Reset settings complete toast text [CHAR LIMIT=75] -->
     <string name="reset_network_complete_toast">Network settings have been reset</string>
 
+    <!-- Ethernet Settings -->
+    <string name="ethernet_ip_hint" translatable="false"> 192.168.0.100</string>
+    <string name="ethernet_gateway_hint" translatable="false"> 192.168.0.1</string>
+    <string name="ethernet_netmask_hint" translatable="false"> 255.255.255.0</string>
+    <string name="ethernet_dns1_hint" translatable="false"> 0.0.0.0</string>
+    <string name="ethernet_dns2_hint" translatable="false"> 0.0.0.0</string>
+
+    <string name="ethernet_mac">MAC</string>
+    <string name="ethernet_ip_addr">IP Address</string>
+    <string name="ethernet_netmask">Network Mask</string>
+    <string name="ethernet_gateway">Gateway</string>
+    <string name="ethernet_dns1">DNS 1</string>
+    <string name="ethernet_dns2">DNS 2</string>
+
+    <string name="ethernet_settings_title">Ethernet</string>
+    <string name="ethernet_settings">Ethernet</string>
+    <string name="ethernet_connect">Connect</string>
+    <string name="ethernet_cancel">Cancel</string>
+    <string name="ethernet_dhcp">DHCP</string>
+    <string name="ethernet_static">Static</string>
+    <string name="ethernet_mode_title">Ethernet IP Mode</string>
+    <string name="ethernet_info_getting">Getting IP…</string>
+
     <!-- Master Clear -->
     <!-- Button title to factory data reset the entire device -->
     <string name="master_clear_title">Erase all data (factory reset)</string>
diff --git a/packages/apps/Settings/res/xml/ethernet_settings.xml b/packages/apps/Settings/res/xml/ethernet_settings.xml
new file mode 100755
index 0000000..5394734
--- /dev/null
+++ b/packages/apps/Settings/res/xml/ethernet_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+    android:title="@string/ethernet_settings">
+
+    <!--ethernet mac-->
+    <Preference
+        style="?android:preferenceInformationStyle"
+        android:key="ethernet_mac"
+        android:summary="@string/device_info_default"
+        android:title="@string/ethernet_mac" />
+
+    <!-- ethernet ip address -->
+    <Preference
+        style="?android:preferenceInformationStyle"
+        android:key="ethernet_ip_addr"
+        android:summary="@string/device_info_default"
+        android:title="@string/ethernet_ip_addr" />
+
+    <!-- ethernet netmask -->
+    <Preference
+        style="?android:preferenceInformationStyle"
+        android:key="ethernet_netmask"
+        android:summary="@string/device_info_default"
+        android:title="@string/ethernet_netmask" />
+
+    <!-- ethernet mGatewayEdt -->
+    <Preference
+        style="?android:preferenceInformationStyle"
+        android:key="ethernet_gateway"
+        android:summary="@string/device_info_default"
+        android:title="@string/ethernet_gateway" />
+
+    <!-- ethernet mDns1Edt -->
+    <Preference
+        style="?android:preferenceInformationStyle"
+        android:key="ethernet_dns1"
+        android:summary="@string/device_info_default"
+        android:title="@string/ethernet_dns1" />
+
+    <!-- ethernet mDns2Edt -->
+    <Preference
+        style="?android:preferenceInformationStyle"
+        android:key="ethernet_dns2"
+        android:summary="@string/device_info_default"
+        android:title="@string/ethernet_dns2" />
+
+    <ListPreference
+        android:entries="@array/ethernet_mode_location"
+        android:entryValues="@array/ethernet_mode_values"
+        android:key="ethernet_mode_select"
+        android:persistent="true"
+        android:title="@string/ethernet_mode_title" />
+
+</PreferenceScreen>
diff --git a/packages/apps/Settings/res/xml/network_and_internet.xml b/packages/apps/Settings/res/xml/network_and_internet.xml
old mode 100644
new mode 100755
index ee25bee..17281fa
--- a/packages/apps/Settings/res/xml/network_and_internet.xml
+++ b/packages/apps/Settings/res/xml/network_and_internet.xml
@@ -85,5 +85,13 @@
         android:fragment="com.android.settings.ProxySelector"
         android:key="proxy_settings"
         android:title="@string/proxy_settings_title"/>
+
+    <com.android.settingslib.RestrictedPreference
+        android:key="ethernet_settings"
+        android:title="@string/ethernet_settings_title"
+        android:icon="@drawable/ic_ethernet"
+        settings:userRestriction="no_ethernet_settings"
+        settings:useAdminDisabledSummary="true"
+        android:fragment="com.android.settings.ethernet.EthernetSettings" />
 
 </PreferenceScreen>
\ No newline at end of file
diff --git a/packages/apps/Settings/src/com/android/settings/ethernet/EthernetSettings.java b/packages/apps/Settings/src/com/android/settings/ethernet/EthernetSettings.java
new file mode 100755
index 0000000..5c966aa
--- /dev/null
+++ b/packages/apps/Settings/src/com/android/settings/ethernet/EthernetSettings.java
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.ethernet;
+
+import android.app.Dialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.EthernetManager;
+import android.net.IpConfiguration;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.net.StaticIpConfiguration;
+import android.os.Bundle;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+public class EthernetSettings extends SettingsPreferenceFragment
+        implements DialogInterface.OnClickListener, Preference.OnPreferenceChangeListener {
+    private static final String TAG = "EthernetSettings";
+
+    private static final int CONFIG_STATIC_IP_DIALOG = 0;
+
+    private static final String KEY_ETH_IP_ADDRESS = "ethernet_ip_addr";
+    private static final String KEY_ETH_HW_ADDRESS = "ethernet_mac";
+    private static final String KEY_ETH_NET_MASK = "ethernet_netmask";
+    private static final String KEY_ETH_GATEWAY = "ethernet_gateway";
+    private static final String KEY_ETH_DNS1 = "ethernet_dns1";
+    private static final String KEY_ETH_DNS2 = "ethernet_dns2";
+    private static final String KEY_ETH_MODE = "ethernet_mode_select";
+
+    private final static String NULL_IP = "0.0.0.0";
+
+    private static String sEthMac = null;
+    private static String sEthIpAddress = null;
+    private static String sEthNetMask = null;
+    private static String sEthGateway = null;
+    private static String sEthDns1 = null;
+    private static String sEthDns2 = null;
+
+    private Context mContext;
+    private ListPreference mEthMode;
+    private IpConfiguration mIpConfiguration;
+    private EthernetManager mEthManager;
+
+    private EthernetStaticIpDialog mStaticIpDialog;
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.WIFI_TETHER_SETTINGS;
+    }
+
+    @Override
+    public int getDialogMetricsCategory(int dialogId) {
+        switch (dialogId) {
+            case CONFIG_STATIC_IP_DIALOG:
+                return MetricsEvent.WIFI_TETHER_SETTINGS;
+            default:
+                return 0;
+        }
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (EthernetManager.ETHERNET_STATE_CHANGED_ACTION.equals(action)) {
+                int EtherState = intent.getIntExtra(
+                        EthernetManager.EXTRA_ETHERNET_STATE,
+                        -1);
+                handleEtherStateChange(EtherState);
+            }
+        }
+    };
+
+    private void handleEtherStateChange(int state) {
+        Log.i(TAG, "handleEtherStateChange, state" + state);
+
+        switch (state) {
+            case EthernetManager.ETHER_STATE_DISCONNECTED:
+                sEthIpAddress = NULL_IP;
+                sEthNetMask = NULL_IP;
+                sEthGateway = NULL_IP;
+                sEthDns1 = NULL_IP;
+                sEthDns2 = NULL_IP;
+                break;
+
+            case EthernetManager.ETHER_STATE_CONNECTING:
+                String statusStr = mContext.getString(R.string.ethernet_info_getting);
+                sEthIpAddress = statusStr;
+                sEthNetMask = statusStr;
+                sEthGateway = statusStr;
+                sEthDns1 = statusStr;
+                sEthDns2 = statusStr;
+                break;
+
+            case EthernetManager.ETHER_STATE_CONNECTED:
+                getEthInfo();
+                break;
+        }
+
+        update();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.ethernet_settings);
+
+        mEthManager = (EthernetManager) getSystemService(Context.ETHERNET_SERVICE);
+        if (mEthManager == null) {
+            Log.e(TAG, "onCreate, Get ethernet manager failed.");
+            return;
+        }
+
+        sEthMac = getEth0Mac();
+        mContext = this.getActivity().getApplicationContext();
+    }
+
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (mEthMode == null) {
+            mEthMode = (ListPreference) findPreference(KEY_ETH_MODE);
+            mEthMode.setOnPreferenceChangeListener(this);
+        }
+
+        handleEtherStateChange(mEthManager.getEthernetConnectState());
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+
+        mContext.registerReceiver(mReceiver, new IntentFilter(
+                EthernetManager.ETHERNET_STATE_CHANGED_ACTION));
+    }
+
+    @Override
+    public void onStop() {
+        mContext.unregisterReceiver(mReceiver);
+
+        super.onStop();
+    }
+
+    private void setStringSummary(String preference, String value) {
+        try {
+            findPreference(preference).setSummary(value);
+        } catch (RuntimeException e) {
+            findPreference(preference).setSummary("");
+        }
+    }
+
+    private String getStringFromPref(String preference) {
+        try {
+            return findPreference(preference).getSummary().toString();
+        } catch (RuntimeException e) {
+            return null;
+        }
+    }
+
+    private void update() {
+        setStringSummary(KEY_ETH_HW_ADDRESS, sEthMac);
+        setStringSummary(KEY_ETH_IP_ADDRESS, sEthIpAddress);
+        setStringSummary(KEY_ETH_NET_MASK, sEthNetMask);
+        setStringSummary(KEY_ETH_GATEWAY, sEthGateway);
+        setStringSummary(KEY_ETH_DNS1, sEthDns1);
+        setStringSummary(KEY_ETH_DNS2, sEthDns2);
+
+        updateEthMode();
+    }
+
+    private void updateEthMode() {
+        if (mEthManager == null) {
+            mEthMode.setSummary("null");
+        } else {
+            if (mEthManager.getConfiguration().ipAssignment == IpAssignment.DHCP) {
+                mEthMode.setValue("DHCP");
+                mEthMode.setSummary(R.string.ethernet_dhcp);
+            } else {
+                mEthMode.setValue("StaticIP");
+                mEthMode.setSummary(R.string.ethernet_static);
+            }
+        }
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        if (preference == mEthMode) {
+            String value = (String) newValue;
+            if (value.equals("DHCP")) {
+                mEthManager.setConfiguration(new IpConfiguration(IpAssignment.DHCP,
+                        ProxySettings.NONE, null, null));
+            } else if (value.equals("StaticIP")) {
+                this.showDialog(CONFIG_STATIC_IP_DIALOG);
+            }
+        }
+        return true;
+    }
+
+    private Inet4Address getIPv4Address(String text) {
+        try {
+            return (Inet4Address) NetworkUtils.numericToInetAddress(text);
+        } catch (IllegalArgumentException | ClassCastException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Convert netmask
+     *
+     * @param prefixLength
+     * @return
+     */
+    private String interMask2String(int prefixLength) {
+        String netMask = null;
+        int inetMask = prefixLength;
+
+        int part = inetMask / 8;
+        int remainder = inetMask % 8;
+        int sum = 0;
+
+        for (int i = 8; i > 8 - remainder; i--) {
+            sum = sum + (int) Math.pow(2, i - 1);
+        }
+
+        if (part == 0) {
+            netMask = sum + ".0.0.0";
+        } else if (part == 1) {
+            netMask = "255." + sum + ".0.0";
+        } else if (part == 2) {
+            netMask = "255.255." + sum + ".0";
+        } else if (part == 3) {
+            netMask = "255.255.255." + sum;
+        } else if (part == 4) {
+            netMask = "255.255.255.255";
+        }
+
+        return netMask;
+    }
+
+    /*
+     * convert subMask string to prefix length
+     */
+    private int maskStr2InetMask(String maskStr) {
+        StringBuffer sb;
+        String str;
+        int inetmask = 0;
+        int count = 0;
+        /*
+         * check the subMask format
+         */
+        Pattern pattern = Pattern.compile("(^((\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])$)|^(\\d|[1-2]\\d|3[0-2])$");
+        if (!pattern.matcher(maskStr).matches()) {
+            Log.e(TAG, "subMask is error");
+            return 0;
+        }
+
+        String[] ipSegment = maskStr.split("\\.");
+        for (int n = 0; n < ipSegment.length; n++) {
+            sb = new StringBuffer(Integer.toBinaryString(Integer.parseInt(ipSegment[n])));
+            str = sb.reverse().toString();
+            count = 0;
+            for (int i = 0; i < str.length(); i++) {
+                i = str.indexOf("1", i);
+                if (i == -1)
+                    break;
+                count++;
+            }
+            inetmask += count;
+        }
+        return inetmask;
+    }
+
+    private boolean setStaticIpConfiguration() {
+        StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
+
+        Inet4Address inet = getIPv4Address(sEthIpAddress);
+        int prefixLength = maskStr2InetMask(sEthNetMask);
+        InetAddress gateway = getIPv4Address(sEthGateway);
+        InetAddress dns = getIPv4Address(sEthDns1);
+
+        if (null == inet || null == gateway || null == dns
+                || inet.getAddress().length <= 0
+                || prefixLength == 0
+                || gateway.toString().isEmpty()
+                || dns.toString().isEmpty()) {
+            Log.e(TAG, "setStaticIpConfiguration, ip, mask or dns is wrong");
+            return false;
+        }
+
+        staticIpConfiguration.ipAddress = new LinkAddress(inet, prefixLength);
+        staticIpConfiguration.gateway = gateway;
+        staticIpConfiguration.dnsServers.add(dns);
+
+        if (!sEthDns2.isEmpty()) {
+            staticIpConfiguration.dnsServers.add(getIPv4Address(sEthDns2));
+        }
+        mIpConfiguration = new IpConfiguration(IpAssignment.STATIC, ProxySettings.NONE, staticIpConfiguration, null);
+
+        return true;
+    }
+
+    private void getEthInfoFromDhcp() {
+        String tempIpInfo;
+
+        tempIpInfo = mEthManager.getIpAddress();
+
+        if ((tempIpInfo != null) && (!tempIpInfo.equals(""))) {
+            sEthIpAddress = tempIpInfo;
+        } else {
+            sEthIpAddress = NULL_IP;
+        }
+
+        tempIpInfo = mEthManager.getNetmask();
+        if ((tempIpInfo != null) && (!tempIpInfo.equals(""))) {
+            sEthNetMask = tempIpInfo;
+        } else {
+            sEthNetMask = NULL_IP;
+        }
+
+        tempIpInfo = mEthManager.getGateway();
+        if ((tempIpInfo != null) && (!tempIpInfo.equals(""))) {
+            sEthGateway = tempIpInfo;
+        } else {
+            sEthGateway = NULL_IP;
+        }
+
+        tempIpInfo = mEthManager.getDns();
+        if ((tempIpInfo != null) && (!tempIpInfo.equals(""))) {
+            String data[] = tempIpInfo.split(",");
+            sEthDns1 = data[0];
+            if (data.length <= 1) {
+                sEthDns2 = NULL_IP;
+            } else {
+                sEthDns2 = data[1];
+            }
+        } else {
+            sEthDns1 = NULL_IP;
+        }
+    }
+
+    private void getEthInfoFromStaticIp() {
+        StaticIpConfiguration staticIpConfiguration = mEthManager.getConfiguration().getStaticIpConfiguration();
+
+        if (staticIpConfiguration == null) {
+            Log.w(TAG, "getEthInfoFromStaticIp, staticIpConfiguration is null");
+            return;
+        }
+
+        LinkAddress ipAddress = staticIpConfiguration.ipAddress;
+        InetAddress gateway = staticIpConfiguration.gateway;
+        ArrayList<InetAddress> dnsServers = staticIpConfiguration.dnsServers;
+
+        if (ipAddress != null) {
+            sEthIpAddress = ipAddress.getAddress().getHostAddress();
+            sEthNetMask = interMask2String(ipAddress.getPrefixLength());
+        }
+
+        if (gateway != null) {
+            sEthGateway = gateway.getHostAddress();
+        }
+
+        sEthDns1 = dnsServers.get(0).getHostAddress();
+        if (dnsServers.size() > 1) {
+            sEthDns2 = dnsServers.get(1).getHostAddress();
+        }
+    }
+
+    private void getEthInfo() {
+        IpAssignment mode = mEthManager.getConfiguration().getIpAssignment();
+        if (mode == IpAssignment.DHCP) {
+            getEthInfoFromDhcp();
+        } else if (mode == IpAssignment.STATIC) {
+            getEthInfoFromStaticIp();
+        }
+    }
+
+    private static String getEth0Mac() {
+        if (TextUtils.isEmpty(sEthMac)) {
+            try {
+                int numRead = 0;
+                char[] buf = new char[1024];
+                StringBuffer strBuf = new StringBuffer(1000);
+                BufferedReader reader = new BufferedReader(new FileReader(
+                        "/sys/class/net/eth0/address"));
+                while ((numRead = reader.read(buf)) != -1) {
+                    String readData = String.valueOf(buf, 0, numRead);
+                    strBuf.append(readData);
+                }
+                sEthMac = strBuf.toString().replaceAll("\r|\n", "");
+                reader.close();
+            } catch (IOException ex) {
+                Log.w(TAG, "eth0 mac not exist");
+            }
+        }
+        return sEthMac;
+    }
+
+    @Override
+    public void onClick(DialogInterface dialogInterface, int button) {
+        if (button == EthernetStaticIpDialog.BUTTON_SUBMIT) {
+            mStaticIpDialog.saveIpSettingInfo();
+            if (setStaticIpConfiguration()) {
+                mEthManager.setConfiguration(mIpConfiguration);
+            } else {
+                Log.e(TAG, "Set configuration failed: " + mIpConfiguration.toString());
+            }
+        }
+        updateEthMode();
+    }
+
+    @Override
+    public Dialog onCreateDialog(int dialogId) {
+        switch (dialogId) {
+            case CONFIG_STATIC_IP_DIALOG:
+                mStaticIpDialog = new EthernetStaticIpDialog(getActivity(),
+                        false, this, mStaticIpListener);
+                return mStaticIpDialog;
+        }
+        return super.onCreateDialog(dialogId);
+    }
+
+    private IStaticIpListener mStaticIpListener = new IStaticIpListener() {
+
+        public boolean getStaticIp(String ipAddr) {
+            sEthIpAddress = ipAddr;
+
+            Log.i(TAG, "getStaticIp, ipAddr: " + ipAddr);
+            return true;
+        }
+
+        public boolean getStaticNetMask(String netMask) {
+            sEthNetMask = netMask;
+
+            Log.i(TAG, "getStaticNetMask, netMask: " + netMask);
+            return true;
+        }
+
+        public boolean getStaticGateway(String gateway) {
+            sEthGateway = gateway;
+
+            Log.i(TAG, "getStaticGateway, mGatewayEdt: " + gateway);
+            return true;
+        }
+
+        public boolean getStaticDns1(String dns1) {
+            sEthDns1 = dns1;
+
+            Log.i(TAG, "getStaticDns1, mDns1Edt: " + dns1);
+            return true;
+        }
+
+        public boolean getStaticDns2(String dns2) {
+            sEthDns2 = dns2;
+
+            Log.i(TAG, "getStaticDns2, mDns2Edt: " + dns2);
+            return true;
+        }
+    };
+}
\ No newline at end of file
diff --git a/packages/apps/Settings/src/com/android/settings/ethernet/EthernetStaticIpDialog.java b/packages/apps/Settings/src/com/android/settings/ethernet/EthernetStaticIpDialog.java
new file mode 100755
index 0000000..4a98651
--- /dev/null
+++ b/packages/apps/Settings/src/com/android/settings/ethernet/EthernetStaticIpDialog.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.ethernet;
+
+import android.annotation.SuppressLint;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.EthernetManager;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.View;
+import android.widget.EditText;
+
+import com.android.settings.R;
+
+import java.util.regex.Pattern;
+
+class EthernetStaticIpDialog extends AlertDialog implements TextWatcher {
+
+    private IStaticIpListener mStaticIpListener;
+    private EditText mIpEdt;
+    private EditText mGatewayEdt;
+    private EditText mNetmaskEdt;
+    private EditText mDns1Edt;
+    private EditText mDns2Edt;
+
+    @SuppressLint("InlinedApi")
+    static final int BUTTON_SUBMIT = DialogInterface.BUTTON_POSITIVE;
+    @SuppressLint("InlinedApi")
+    static final int BUTTON_FORGET = DialogInterface.BUTTON_NEUTRAL;
+
+    private final static String NULL_IP = "0.0.0.0";
+
+    private Context mContext;
+    private EthernetManager mEthManager;
+    private DialogInterface.OnClickListener mListener;
+
+    EthernetStaticIpDialog(Context context, boolean cancelable,
+                           DialogInterface.OnClickListener listener, IStaticIpListener staticIpListener) {
+        super(context);
+        mContext = context;
+        mListener = listener;
+        mStaticIpListener = staticIpListener;
+    }
+
+    protected EthernetStaticIpDialog(Context context) {
+        super(context);
+    }
+
+    protected EthernetStaticIpDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
+        super(context, cancelable, cancelListener);
+    }
+
+    protected EthernetStaticIpDialog(Context context, int themeResId) {
+        super(context, themeResId);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        View view = getLayoutInflater().inflate(R.layout.static_ip_dialog, null);
+        setView(view);
+        setInverseBackgroundForced(true);
+
+        mIpEdt = (EditText) view.findViewById(R.id.edt_ip);
+        mNetmaskEdt = (EditText) view.findViewById(R.id.edt_netmask);
+        mGatewayEdt = (EditText) view.findViewById(R.id.edt_gateway);
+        mDns1Edt = (EditText) view.findViewById(R.id.edt_dns1);
+        mDns2Edt = (EditText) view.findViewById(R.id.edt_dns2);
+
+        mIpEdt.addTextChangedListener(this);
+        mNetmaskEdt.addTextChangedListener(this);
+        mGatewayEdt.addTextChangedListener(this);
+        mDns1Edt.addTextChangedListener(this);
+        mDns2Edt.addTextChangedListener(this);
+
+        setButton(BUTTON_SUBMIT, mContext.getString(R.string.ethernet_connect), mListener);
+        setButton(BUTTON_NEGATIVE, mContext.getString(R.string.ethernet_cancel), mListener);
+        setTitle(mContext.getString(R.string.ethernet_settings));
+
+        mEthManager = (EthernetManager) mContext.getSystemService(Context.ETHERNET_SERVICE);
+
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+
+        updateIpSettingsInfo();
+        checkIPValue();
+    }
+
+    private void updateIpSettingsInfo() {
+        String ip = mEthManager.getIpAddress();
+        if (!TextUtils.isEmpty(ip)) {
+            mIpEdt.setText(ip);
+        }
+
+        String netMask = mEthManager.getNetmask();
+        if (!TextUtils.isEmpty(netMask)) {
+            mNetmaskEdt.setText(netMask);
+        }
+
+        String gateway = mEthManager.getGateway();
+        if (!TextUtils.isEmpty(gateway)) {
+            mGatewayEdt.setText(gateway);
+        }
+
+        String dns = mEthManager.getDns();
+        String dns1 = NULL_IP;
+        String dns2 = NULL_IP;
+        if (!TextUtils.isEmpty(dns)) {
+            String data[] = dns.split(",");
+            dns1 = data[0];
+            if (data.length > 1)
+                dns2 = data[1];
+        }
+        if (!TextUtils.isEmpty(dns1)) {
+            mDns1Edt.setText(dns1);
+        }
+        if (!TextUtils.isEmpty(dns2)) {
+            mDns2Edt.setText(dns2);
+        }
+    }
+
+    void saveIpSettingInfo() {
+        String ip = mIpEdt.getText().toString();
+        String gateway = mGatewayEdt.getText().toString();
+        String netMask = mNetmaskEdt.getText().toString();
+        String dns1 = mDns1Edt.getText().toString();
+        String dns2 = mDns2Edt.getText().toString();
+
+        mStaticIpListener.getStaticIp(ip);
+        mStaticIpListener.getStaticNetMask(netMask);
+        mStaticIpListener.getStaticGateway(gateway);
+        mStaticIpListener.getStaticDns1(dns1);
+        mStaticIpListener.getStaticDns2(dns2);
+    }
+
+    private boolean isValidIpAddress(String value) {
+        int start = 0;
+        int end = value.indexOf('.');
+        int numBlocks = 0;
+
+        while (start < value.length()) {
+            if (-1 == end) {
+                end = value.length();
+            }
+
+            try {
+                int block = Integer.parseInt(value.substring(start, end));
+                if ((block > 255) || (block < 0)) {
+                    Log.w("EthernetIP",
+                            "isValidIpAddress() : invalid 'block', block = "
+                                    + block);
+                    return false;
+                }
+            } catch (NumberFormatException e) {
+                Log.w("EthernetIP", "isValidIpAddress() : e = " + e);
+                return false;
+            }
+
+            numBlocks++;
+
+            start = end + 1;
+            end = value.indexOf('.', start);
+        }
+        return numBlocks == 4;
+    }
+
+    private void checkIPValue() {
+        boolean enable = false;
+
+        String ip = mIpEdt.getText().toString();
+        String gateway = mGatewayEdt.getText().toString();
+        String dns1 = mDns1Edt.getText().toString();
+        String dns2 = mDns2Edt.getText().toString();
+        String netMask = mNetmaskEdt.getText().toString();
+
+        Pattern pattern = Pattern.compile("(^((\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])$)|^(\\d|[1-2]\\d|3[0-2])$"); /*check subnet mask*/
+        if (isValidIpAddress(ip) && isValidIpAddress(gateway)
+                && isValidIpAddress(dns1) && (pattern.matcher(netMask).matches())) {
+            if (TextUtils.isEmpty(dns2)) {
+                enable = true;
+            } else {
+                enable = isValidIpAddress(dns2);
+            }
+        }
+
+        getButton(BUTTON_SUBMIT).setEnabled(enable);
+
+    }
+
+    @Override
+    public void afterTextChanged(Editable s) {
+        checkIPValue();
+    }
+
+    @Override
+    public void beforeTextChanged(CharSequence s, int start, int count,
+                                  int after) {
+    }
+
+    @Override
+    public void onTextChanged(CharSequence s, int start, int before, int count) {
+    }
+}
\ No newline at end of file
diff --git a/packages/apps/Settings/src/com/android/settings/ethernet/IStaticIpListener.java b/packages/apps/Settings/src/com/android/settings/ethernet/IStaticIpListener.java
new file mode 100755
index 0000000..b2b7dfb
--- /dev/null
+++ b/packages/apps/Settings/src/com/android/settings/ethernet/IStaticIpListener.java
@@ -0,0 +1,9 @@
+package com.android.settings.ethernet;
+
+public interface IStaticIpListener {
+	public boolean getStaticIp(String ip);
+	public boolean getStaticNetMask(String netMask);
+	public boolean getStaticGateway(String gateway);
+	public boolean getStaticDns1(String dns1);
+	public boolean getStaticDns2(String dns2);
+}
\ No newline at end of file

解决修改以太网配置后立即断电配置丢失问题

因为以太网配置结果是保存在本地文件中,当设置完成后立即断电,文件还在缓存中,并未真正写到磁盘,所以会导致配置丢失。这里在修改配置完成后增加磁盘同步,强制文件写入磁盘,从而解决断电配置丢失问题。

commit abdc52ad35ba218c09f7ac4f84b2a653bd6220f5
Author: shenhb <shenhb@topband.com.cn>
Date:   Tue Nov 12 15:02:02 2019 +0800

    【以太网】解决修改以太网配置项后立即断电配置丢失问题

diff --git a/frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetConfigStore.java b/frameworks/op
index dad5dea..7d38693 100755
--- a/frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetConfigStore.java
+++ b/frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetConfigStore.java
@@ -25,6 +25,7 @@ import android.util.SparseArray;
 import android.os.SystemProperties;
 import com.android.server.net.IpConfigStore;
 import java.io.File;
+import java.io.IOException;
 
 /**
  * This class provides an API to store and manage Ethernet network configuration.
@@ -64,5 +65,10 @@ public class EthernetConfigStore extends IpConfigStore {
         SparseArray<IpConfiguration> networks = new SparseArray<IpConfiguration>();
         networks.put(0, config);
         writeIpAndProxyConfigurations(ipConfigFile, networks);
+        try {
+            Runtime.getRuntime().exec("sync");
+        } catch (IOException e) {
+            Log.e(TAG, "writeIpAndProxyConfigurations, sync error: " + e.getMessage());
+        }
     }
 }

二、Android支持多摄像头

某些平台默认只支持2个摄像头,但随着 AI 越来越热门,图像识别应用越来越广泛,我们经常需要用到更多的摄像头。下面修改使 Android 能够支持最多10个摄像头。

commit 840a47894a1160cdc96189113c5e9ba82efbeaab
Author: shenhb <shenhb@topband.com.cn>
Date:   Mon Dec 17 17:09:35 2018 +0800

    【摄像头】支持大于2个摄像头

diff --git a/hardware/rockchip/camera/CameraHal/CameraHal_Module.cpp b/hardware/rockchip/camera/CameraHal/CameraHal_Module.cpp
index 3365339..0f58fa4 100755
--- a/hardware/rockchip/camera/CameraHal/CameraHal_Module.cpp
+++ b/hardware/rockchip/camera/CameraHal/CameraHal_Module.cpp
@@ -787,18 +787,18 @@ int camera_get_number_of_cameras(void)
         	if(profiles->mDevieVector[i]->mIsConnect==1){
     	        rk_sensor_info *pSensorInfo = &(profiles->mDevieVector[i]->mHardInfo.mSensorInfo);
     	        
-    	        camInfoTmp[cam_cnt&0x01].pcam_total_info = profiles->mDevieVector[i];     
-    	        strncpy(camInfoTmp[cam_cnt&0x01].device_path, pSensorInfo->mCamsysDevPath, sizeof(camInfoTmp[cam_cnt&0x01].device_path));
-    	        strncpy(camInfoTmp[cam_cnt&0x01].driver, pSensorInfo->mSensorDriver, sizeof(camInfoTmp[cam_cnt&0x01].driver));
+    	        camInfoTmp[cam_cnt].pcam_total_info = profiles->mDevieVector[i];     
+    	        strncpy(camInfoTmp[cam_cnt].device_path, pSensorInfo->mCamsysDevPath, sizeof(camInfoTmp[cam_cnt].device_path));
+    	        strncpy(camInfoTmp[cam_cnt].driver, pSensorInfo->mSensorDriver, sizeof(camInfoTmp[cam_cnt].driver));
 				unsigned int SensorDrvVersion = profiles->mDevieVector[i]->mLoadSensorInfo.mpI2cInfo->sensor_drv_version;
 				memset(version,0x00,sizeof(version));
     	        sprintf(version,"%d.%d.%d",((SensorDrvVersion&0xff0000)>>16),
 	    	            ((SensorDrvVersion&0xff00)>>8),SensorDrvVersion&0xff);
 						 
     	        if(pSensorInfo->mFacing == RK_CAM_FACING_FRONT){     
-    	            camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_FRONT;	    	        
+    	            camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_FRONT;	    	        
     	        } else {
-    	            camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_BACK;
+    	            camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_BACK;
     	        } 
 
                 memset(sensor_ver,0x00,sizeof(sensor_ver));
@@ -808,7 +808,7 @@ int camera_get_number_of_cameras(void)
                     sprintf(sensor_ver,"%s",pSensorInfo->mSensorName);                
                 property_set(sensor_ver, version);	
                 
-    	        camInfoTmp[cam_cnt&0x01].facing_info.orientation = pSensorInfo->mOrientation;
+    	        camInfoTmp[cam_cnt].facing_info.orientation = pSensorInfo->mOrientation;
     	        cam_cnt++;
 
     			unsigned int CamsysDrvVersion = profiles->mDevieVector[i]->mCamsysVersion.drv_ver;
@@ -842,7 +842,7 @@ int camera_get_number_of_cameras(void)
             fd = open(cam_path, O_RDONLY);
             if (fd < 0) {
                 LOGE("Open %s failed! strr: %s",cam_path,strerror(errno));
-                break;
+                continue;
             } 
             LOGD("Open %s success!",cam_path);
 
@@ -856,31 +856,32 @@ int camera_get_number_of_cameras(void)
         	    LOGD("Video device(%s): video capture not supported.\n",cam_path);
             } else {
             	rk_cam_total_info* pNewCamInfo = new rk_cam_total_info();
-                memset(camInfoTmp[cam_cnt&0x01].device_path,0x00, sizeof(camInfoTmp[cam_cnt&0x01].device_path));
-                strcat(camInfoTmp[cam_cnt&0x01].device_path,cam_path);
-                memset(camInfoTmp[cam_cnt&0x01].fival_list,0x00, sizeof(camInfoTmp[cam_cnt&0x01].fival_list));
-                memcpy(camInfoTmp[cam_cnt&0x01].driver,capability.driver, sizeof(camInfoTmp[cam_cnt&0x01].driver));
-                camInfoTmp[cam_cnt&0x01].version = capability.version;
+                memset(camInfoTmp[cam_cnt].device_path,0x00, sizeof(camInfoTmp[cam_cnt].device_path));
+                strcat(camInfoTmp[cam_cnt].device_path,cam_path);
+                memset(camInfoTmp[cam_cnt].fival_list,0x00, sizeof(camInfoTmp[cam_cnt].fival_list));
+                memcpy(camInfoTmp[cam_cnt].driver,capability.driver, sizeof(camInfoTmp[cam_cnt].driver));
+                camInfoTmp[cam_cnt].version = capability.version;
+
                 if (strstr((char*)&capability.card[0], "front") != NULL) {
-                    camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_FRONT;
+                    camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_FRONT;
 #ifdef LAPTOP
                 } else if (strstr((char*)&capability.card[0], "HP HD") != NULL
                     || strstr((char*)&capability.card[0], "HP IR")) {
-                    camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_FRONT;
+                    camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_FRONT;
                     if (strstr((char*)&capability.card[0], "HP IR"))
                         gCamerasUnavailabled++;
-                    gUsbCameraNames[cam_cnt&0x01] = String8((char*)&capability.card[0]);
-                    LOGD("Camera %d name: %s", (cam_cnt&0x01), gUsbCameraNames[cam_cnt&0x01].string());
+                    gUsbCameraNames[cam_cnt] = String8((char*)&capability.card[0]);
+                    LOGD("Camera %d name: %s", (cam_cnt), gUsbCameraNames[cam_cnt].string());
 #endif
                 } else {
-                    camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_BACK;
+                    camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_BACK;
                 }  
                 ptr = strstr((char*)&capability.card[0],"-");
                 if (ptr != NULL) {
                     ptr++;
-                    camInfoTmp[cam_cnt&0x01].facing_info.orientation = atoi(ptr);
+                    camInfoTmp[cam_cnt].facing_info.orientation = atoi(ptr);
                 } else {
-                    camInfoTmp[cam_cnt&0x01].facing_info.orientation = 0;
+                    camInfoTmp[cam_cnt].facing_info.orientation = 0;
                 }
 
                 memset(version,0x00,sizeof(version));
@@ -1207,17 +1208,17 @@ int camera_get_number_of_cameras(void)
     }
 #endif    
 
-    #if CONFIG_CAMERA_SINGLE_SENSOR_FORCE_BACK_FOR_CTS
+#if CONFIG_CAMERA_SINGLE_SENSOR_FORCE_BACK_FOR_CTS
     if ((gCamerasNumber==1) && (camInfoTmp[0].facing_info.facing==CAMERA_FACING_FRONT)) {
         gCamerasNumber = 2;
         memcpy(&camInfoTmp[1],&camInfoTmp[0], sizeof(rk_cam_info_t));
         camInfoTmp[1].facing_info.facing = CAMERA_FACING_BACK;
     }
-    #endif
+#endif
     
-    memcpy(&gCamInfos[0], &camInfoTmp[0], sizeof(rk_cam_info_t));
-    memcpy(&gCamInfos[1], &camInfoTmp[1], sizeof(rk_cam_info_t));
-
+    for (int i = 0; i < gCamerasNumber; i++) {
+        memcpy(&gCamInfos[i], &camInfoTmp[i], sizeof(rk_cam_info_t));
+    }
 
     property_get("ro.sf.hwrotation", property, "0");
     hwrotation = strtol(property,0,0);
@@ -1294,22 +1295,22 @@ int camera_get_number_of_cameras(void)
         if ((capability.capabilities & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING)) != (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING)) {
     	    LOGD("Video device(%s): video capture not supported.\n",cam_path);
         } else {
-            memset(camInfoTmp[cam_cnt&0x01].device_path,0x00, sizeof(camInfoTmp[cam_cnt&0x01].device_path));
-            strcat(camInfoTmp[cam_cnt&0x01].device_path,cam_path);
-            memset(camInfoTmp[cam_cnt&0x01].fival_list,0x00, sizeof(camInfoTmp[cam_cnt&0x01].fival_list));
-            memcpy(camInfoTmp[cam_cnt&0x01].driver,capability.driver, sizeof(camInfoTmp[cam_cnt&0x01].driver));
-            camInfoTmp[cam_cnt&0x01].version = capability.version;
+            memset(camInfoTmp[cam_cnt].device_path,0x00, sizeof(camInfoTmp[cam_cnt].device_path));
+            strcat(camInfoTmp[cam_cnt].device_path,cam_path);
+            memset(camInfoTmp[cam_cnt].fival_list,0x00, sizeof(camInfoTmp[cam_cnt].fival_list));
+            memcpy(camInfoTmp[cam_cnt].driver,capability.driver, sizeof(camInfoTmp[cam_cnt].driver));
+            camInfoTmp[cam_cnt].version = capability.version;
             if (strstr((char*)&capability.card[0], "front") != NULL) {
-                camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_FRONT;
+                camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_FRONT;
             } else {
-                camInfoTmp[cam_cnt&0x01].facing_info.facing = CAMERA_FACING_BACK;
+                camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_BACK;
             }  
             ptr = strstr((char*)&capability.card[0],"-");
             if (ptr != NULL) {
                 ptr++;
-                camInfoTmp[cam_cnt&0x01].facing_info.orientation = atoi(ptr);
+                camInfoTmp[cam_cnt].facing_info.orientation = atoi(ptr);
             } else {
-                camInfoTmp[cam_cnt&0x01].facing_info.orientation = 0;
+                camInfoTmp[cam_cnt].facing_info.orientation = 0;
             }
             cam_cnt++;
 
diff --git a/hardware/rockchip/camera/CameraHal/CameraHal_Module.h b/hardware/rockchip/camera/CameraHal/CameraHal_Module.h
index dc619eb..98f5d8e 100755
--- a/hardware/rockchip/camera/CameraHal/CameraHal_Module.h
+++ b/hardware/rockchip/camera/CameraHal/CameraHal_Module.h
@@ -11,12 +11,8 @@ using namespace android;
 #define CAMERA_DEFAULT_PREVIEW_FPS_MIN    8000        //8 fps
 #define CAMERA_DEFAULT_PREVIEW_FPS_MAX    15000
 #endif
-#define CAMERAS_SUPPORT_MAX             2
-#if 1//defined(TARGET_RK3399)
-    #define CAMERAS_SUPPORTED_SIMUL_MAX     2
-#else
-    #define CAMERAS_SUPPORTED_SIMUL_MAX     1
-#endif
+#define CAMERAS_SUPPORT_MAX             10
+#define CAMERAS_SUPPORTED_SIMUL_MAX     10
 #define CAMERA_DEVICE_NAME              "/dev/video"
 #define CAMERA_MODULE_NAME              "RK29_ICS_CameraHal_Module"
 

三、Android替换默认签名

生成自定义签名
创建签名生成脚本
创建 build/make/target/product/security/mkkey.sh 文件,内容如下:

#/bin/sh!
if [ $# -ne 1 ] ; then
	echo "Create a test certificate key."
	echo "Usage: $0 NAME"
	echo "Will generate NAME.pk8 and NAME.x509.pem"
	echo "/C=CN/ST=Guangdong/L=ShenZhen/O=Company/OU=Team/CN=Company/emailAddress=xxx@gmail.com"
	exit 1
fi

openssl genrsa -3 -out $1.pem 2048

openssl req -new -x509 -key $1.pem -out $1.x509.pem -days 10000 \
    -subj '/C=CN/ST=Guangdong/L=ShenZhen/O=Company/OU=Team/CN=Company/emailAddress=xxx@gmail.com' 

openssl pkcs8 -in $1.pem -topk8 -outform DER -out $1.pk8 -nocrypt

其中 『-subj』参数请替换为自定义值。

生成签名
通过 mkkey.sh,分别生成 media、platform、shared、testkey、verity 相关 key。

./mkkey.sh media
./mkkey.sh platform
./mkkey.sh shared
./mkkey.sh testkey
./mkkey.sh verity

生成文件如下:

.
├── Android.mk
├── media.pem
├── media.pk8
├── media.x509.pem
├── mkkey.sh
├── platform.pem
├── platform.pk8
├── platform.x509.pem
├── README
├── shared.pem
├── shared.pk8
├── shared.x509.pem
├── testkey.pem
├── testkey.pk8
├── testkey.x509.pem
├── verity_key
├── verity.pk8
└── verity.x509.pem

对全部内置应用重新签名
现在已经生成了自定义签名,但原内置的很多预编译应用还是使用的原 Android 默认签名,如果不对这些应用进行重新签名,将无法使用。所以,这里需要对全部预编译应用使用新的签名 key 进行重新签名。
创建批量签名脚本
创建批量签名脚本:vendor/rockchip/common/apps/ApkBatchSign/apksign.sh,内容如下:

#!/bin/bash

usage()
{
    echo "USAGE: [r] [-s source directory] [-k key directory]"
    echo "No ARGS means use default build option"
    echo "WHERE: -s = set source directory"
    echo "       -k = key directory"
    echo "       -r = replace source file"
    echo "       -h = help"
    exit 1
}

CUR_DIR=$PWD
SOURCE=$CUR_DIR
SIGNAPK_JAR=signapk.jar
KEY=$CUR_DIR
REPLACE=false

while getopts "s:k:r" opt
do
    case $opt in
        s)
		SOURCE=$OPTARG
        ;;
		k)
        KEY=$OPTARG
        ;;
		r)
        REPLACE=true
        ;;
        h)
        usage ;;
        ?)
        usage ;;
    esac
done


function sign(){
    for filename in $1/*
    do  
        if [ -d $filename ]
        then 
            sign $filename
        elif [ "${filename##*.}" = "apk" ]; then
            echo "签名: "$filename
		
			tempname=$(dirname $filename)"/"$(basename $filename .apk)"_signed.apk"
			java -jar $KEY/signapk.jar $KEY/platform.x509.pem $KEY/platform.pk8 $filename $tempname
			
			if [ $REPLACE = true ]; then
				rm -rf $filename
				mv -vf $tempname $filename
			fi
        fi  
    done
}

sign $SOURCE

使用批量签名脚本对全部应用签名
参数解释:
● -s 指定 APK 路径,默认会递归子目录查找。
● -k 指定签名 key 路径。需要包含下面三个文件:

.
├── platform.pk8
├── platform.x509.pem
└── signapk.jar

例如:

ApkBatchSign$ ./apksign.sh -s . -k topband_sign -r
签名: ./dir/BooksProvider.apk
‘./dir/BooksProvider_signed.apk’ ->./dir/BooksProvider.apk’
签名: ./RkEbookReader.apk
‘./RkEbookReader_signed.apk’ ->./RkEbookReader.apk’

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉亭下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值