aosp13增加摄像头控制功能实现

发布于:2025-04-13 ⋅ 阅读:(16) ⋅ 点赞:(0)

A13中,可以要求做一个开关来控制摄像头是否可用,约束所有使用摄像头的应用。思路:设置中增加开关设置一个属性值,在摄像头调用实现层增该值判断即可        

一 开关的开发:

设置-安全中增加开关选项

代码部分:

Settings/res/xml/security_dashboard_settings.xml

//........忽略代码  
  <Preference
        android:order="100"
        android:key="security_advanced_settings"
        android:title="@string/security_advanced_settings"
        android:summary="@string/summary_placeholder"
        android:fragment="com.android.settings.security.SecurityAdvancedSettings"
        settings:controller="com.android.settings.security.SecurityAdvancedSettingsController"
        settings:keywords="@string/security_advanced_settings_keywords" />
    <Preference
        android:order="90"
        android:title="@string/apk_install_setting">
            <intent
            android:targetPackage="com.android.settings"
            android:targetClass="com.android.settings.security.ApkInstallActivity" />
    </Preference>
    + <Preference
    +    android:order="80"
    +    android:title="@string/custom_function_control_setting">
    +        <intent
    +        android:targetPackage="com.android.settings"
    +      +android:targetClass="com.android.settings.security.CustomFunctionSettingActivity" />
 +   </Preference> 
</PreferenceScreen>

 新增界面,如下,自定义属性字段,可以参考上一篇文章Android SystemProperties 读写机制详解和案例使用 。就是使用开关组件读写属性

package com.android.settings.security;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.app.Activity;
import java.io.IOException;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.android.settings.R;
import android.provider.Settings;
import android.widget.Toast;
import android.text.TextUtils;
import android.os.SystemProperties;

import android.widget.CompoundButton;
import android.content.Context;

import android.widget.Switch;

/**
 * 自定义功能开关
 */
public class CustomFunctionSettingActivity extends Activity implements CompoundButton.OnCheckedChangeListener, View.OnClickListener {

    private Switch cameraSwbtn;    
    private static final String CAMERA_ENABLE_KEY = "persist.sys.flyscale.cam"; 

    private Context mContext;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mContext = this;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.custom_function_control);
        cameraSwbtn = findViewById(R.id.swbtn_camera);
        cameraSwbtn.setOnCheckedChangeListener(this);
        String propValue = SystemProperties.get(CAMERA_ENABLE_KEY, "1"); // 默认启用

        // String cameraEnable = Settings.Global.getString(getContentResolver(), Settings.Global.CUSTOM_FUNCTION_CAMERA_ENABLE);
        if ("1".equals(propValue)) {
          cameraSwbtn.setChecked(true);
        }else {
          cameraSwbtn.setChecked(false);

        }	
        cameraSwbtn.setOnClickListener(this);
    }


    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        // switch (buttonView.getId()) {
        //     case R.id.toggle_button:
        //         Toast.makeText(this, "toggle state changed : " + isChecked, Toast.LENGTH_SHORT).show();
        //         break;
        //     case R.id.switch_button:
        //         Toast.makeText(this, "wlan state changed : " + isChecked, Toast.LENGTH_SHORT).show();
        //         break;
        //     default:
        //         Toast.makeText(this, "no state changed", Toast.LENGTH_SHORT).show();
 
        // }
        if (buttonView== null) {
            return;


        }
        
    }

    @Override
    public void onClick(View v) {
	    if (  v == cameraSwbtn) {
                boolean isChecked = cameraSwbtn.isChecked();
                saveValue(isChecked);
            if (isChecked) {
                Toast.makeText(mContext, R.string.custom_function_camera_change_enable,Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(mContext, R.string.custom_function_camera_change_disable,Toast.LENGTH_SHORT).show();
            }

        }
        
    }

    private void saveValue(boolean enabled) {
        String  value = "0";
        if (enabled) {
           value = "1";
        }else {
            value = "0";
        }
        try {
            SystemProperties.set(CAMERA_ENABLE_KEY, enabled ? "1" : "0");
        } catch (Exception e) {
            Log.e("CustomFunction", "Failed to set property", e);
        }
       // Settings.Global.putString(getContentResolver(), Settings.Global.CUSTOM_FUNCTION_CAMERA_ENABLE,value);

    }
}

布局如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:text="@string/custom_function_control_setting"
        android:textSize="24dp"
        android:layout_margin="10dp"
        android:gravity="center"
        android:textColor="@android:color/black"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:layout_marginTop="30dp"
    android:orientation="horizontal">

      <TextView
        android:textSize="20dp"
        android:layout_marginLeft="10dp"
        android:text="@string/custom_function_control_camera_title"
        android:gravity="center"
        android:textColor="@android:color/black"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>            
        <View android:layout_height="1dp"
             android:layout_weight="1"
            android:layout_width="0dp"/>
        <Switch
            android:id="@+id/swbtn_camera"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:switchMinWidth="0dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="20dp"
            android:showText="false"
            android:switchPadding="10dp"
            android:textOff="close"
            android:textOn="open" />

</LinearLayout>

</LinearLayout>

二 摄像头控制逻辑添加:

//framework/av/services/camera/libcameraservice/CameraService.cpp 下

/**
    * 控制摄像头开关是否允许使用
    */
   const bool USING_CAMERA_ENABLE_LOCK = false;

。。。。。。。。。。。。忽略代码
Status CameraService::connectDevice(
        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
        const String16& cameraId,
        const String16& clientPackageName,
        const std::optional<String16>& clientFeatureId,
        int clientUid, int oomScoreOffset, int targetSdkVersion,
        /*out*/
        sp<hardware::camera2::ICameraDeviceUser>* device) {

    ATRACE_CALL();
    Status ret = Status::ok();
    String8 id = String8(cameraId);
    sp<CameraDeviceClient> client = nullptr;
    String16 clientPackageNameAdj = clientPackageName;
    int callingPid = CameraThreadState::getCallingPid();
    bool systemNativeClient = false;
    if (doesClientHaveSystemUid() && (clientPackageNameAdj.size() == 0)) {
        std::string systemClient =
                StringPrintf("client.pid<%d>", CameraThreadState::getCallingPid());
        clientPackageNameAdj = String16(systemClient.c_str());
        systemNativeClient = true;
    }

    if (oomScoreOffset < 0) {
        String8 msg =
                String8::format("Cannot increase the priority of a client %s pid %d for "
                        "camera id %s", String8(clientPackageNameAdj).string(), callingPid,
                        id.string());
        ALOGE("%s: %s", __FUNCTION__, msg.string());
        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
    }
    
  +  if (USING_CAMERA_ENABLE_LOCK) {
  +      if (!isFlyscaleCameraEnabled()) {
  +          String8 msg =
  +              String8::format("flyscale camera not allow,Camera disabled by device +policy");
 +       ALOGE("%s: %s", __FUNCTION__, msg.string());
 +       return STATUS_ERROR(ERROR_DISABLED, msg.string());
 +       }
 +
 +   }

    if (CameraServiceProxyWrapper::isCameraDisabled()) {
        String8 msg =
                String8::format("Camera disabled by device policy");
        ALOGE("%s: %s", __FUNCTION__, msg.string());
        return STATUS_ERROR(ERROR_DISABLED, msg.string());
    }

    // enforce system camera permissions
    if (oomScoreOffset > 0 &&
            !hasPermissionsForSystemCamera(callingPid, CameraThreadState::getCallingUid())) {
        String8 msg =
                String8::format("Cannot change the priority of a client %s pid %d for "
                        "camera id %s without SYSTEM_CAMERA permissions",
                        String8(clientPackageNameAdj).string(), callingPid, id.string());
        ALOGE("%s: %s", __FUNCTION__, msg.string());
        return STATUS_ERROR(ERROR_PERMISSION_DENIED, msg.string());
    }
。。。。。。。。。。。。。忽略代码

OVER~