dubai: Disable 5G when front camera is in use
On some network(s) (confirmed on Jio), the usage of 5G kills front
camera and crashes the camera app. Logs reveal hardware or firmware
issues related to interference or bandwidth, which is out of my
expertise:
[ 63.301897] CAM_ERR: CAM-ISP: cam_ife_csid_irq: 5016 CSID:2 RX_ERROR_LANE0_FIFO_OVERFLOW: Skew/Less Data on lanes/ Slow csid clock:300000000Hz
Until this can be actually fixed (if ever), a temporary workaround.
Inspired by a860cc8189
Change-Id: Ifefb36cf113a5f25feda771ea7729418553e74ed
This commit is contained in:
parent
ee1e29f6b9
commit
8808e9b818
6 changed files with 243 additions and 0 deletions
22
camera/Android.bp
Normal file
22
camera/Android.bp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// Copyright (C) 2023 ArrowOS
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
android_app {
|
||||||
|
name: "DubaiCameraService",
|
||||||
|
srcs: ["src/**/*.java"],
|
||||||
|
certificate: "platform",
|
||||||
|
platform_apis: true,
|
||||||
|
privileged: true,
|
||||||
|
system_ext_specific: true,
|
||||||
|
required: ["privapp-permissions-dubaicameraservice.xml"],
|
||||||
|
}
|
||||||
|
|
||||||
|
prebuilt_etc {
|
||||||
|
name: "privapp-permissions-dubaicameraservice.xml",
|
||||||
|
src: "privapp-permissions-dubaicameraservice.xml",
|
||||||
|
system_ext_specific: true,
|
||||||
|
sub_dir: "permissions",
|
||||||
|
}
|
34
camera/AndroidManifest.xml
Normal file
34
camera/AndroidManifest.xml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2023 ArrowOS
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
-->
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.arrow.dubaicameraservice"
|
||||||
|
android:sharedUserId="android.uid.system">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:label="DubaiCameraService"
|
||||||
|
android:persistent="true">
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name=".BootReceiver"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter android:priority="1000">
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<service android:name=".DubaiCameraService"
|
||||||
|
android:permission="DubaiCameraService"
|
||||||
|
android:exported="false">
|
||||||
|
</service>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
11
camera/privapp-permissions-dubaicameraservice.xml
Normal file
11
camera/privapp-permissions-dubaicameraservice.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2023 ArrowOS
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
-->
|
||||||
|
<permissions>
|
||||||
|
<privapp-permissions package="com.arrow.dubaicameraservice">
|
||||||
|
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
|
||||||
|
<permission name="android.permission.MODIFY_PHONE_STATE"/>
|
||||||
|
</privapp-permissions>
|
||||||
|
</permissions>
|
22
camera/src/com/arrow/dubaicameraservice/BootReceiver.java
Normal file
22
camera/src/com/arrow/dubaicameraservice/BootReceiver.java
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 ArrowOS
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.arrow.dubaicameraservice;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
public class BootReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(final Context context, Intent intent) {
|
||||||
|
if (!intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED))
|
||||||
|
return;
|
||||||
|
|
||||||
|
DubaiCameraService.startService(context);
|
||||||
|
}
|
||||||
|
}
|
153
camera/src/com/arrow/dubaicameraservice/DubaiCameraService.java
Normal file
153
camera/src/com/arrow/dubaicameraservice/DubaiCameraService.java
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 ArrowOS
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.arrow.dubaicameraservice;
|
||||||
|
|
||||||
|
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
|
import static android.telephony.TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER;
|
||||||
|
import static android.telephony.TelephonyManager.NETWORK_TYPE_BITMASK_NR;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.hardware.camera2.CameraManager;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerExecutor;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
|
import android.telephony.TelephonyCallback;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class DubaiCameraService extends Service {
|
||||||
|
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
private static final String TAG = "DubaiCameraService";
|
||||||
|
|
||||||
|
private static final String FRONT_CAMERA_ID = "1";
|
||||||
|
|
||||||
|
private CameraManager mCameraManager;
|
||||||
|
private SubscriptionManager mSubManager;
|
||||||
|
private TelephonyManager mTelephonyManager;
|
||||||
|
|
||||||
|
private boolean mIsFrontCamInUse = false;
|
||||||
|
private int mSubId = INVALID_SUBSCRIPTION_ID;
|
||||||
|
|
||||||
|
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||||
|
private final Executor mExecutor = new HandlerExecutor(mHandler);
|
||||||
|
|
||||||
|
private final CameraManager.AvailabilityCallback mCameraCallback =
|
||||||
|
new CameraManager.AvailabilityCallback() {
|
||||||
|
@Override
|
||||||
|
public void onCameraAvailable(String cameraId) {
|
||||||
|
dlog("onCameraAvailable id:" + cameraId);
|
||||||
|
if (cameraId.equals(FRONT_CAMERA_ID)) {
|
||||||
|
mIsFrontCamInUse = false;
|
||||||
|
update5gState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraUnavailable(String cameraId) {
|
||||||
|
dlog("onCameraUnavailable id:" + cameraId);
|
||||||
|
if (cameraId.equals(FRONT_CAMERA_ID)) {
|
||||||
|
mIsFrontCamInUse = true;
|
||||||
|
update5gState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final SubscriptionManager.OnSubscriptionsChangedListener mSubListener =
|
||||||
|
new SubscriptionManager.OnSubscriptionsChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onSubscriptionsChanged() {
|
||||||
|
dlog("onSubscriptionsChanged");
|
||||||
|
update5gState();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private class ActiveDataSubIdCallback extends TelephonyCallback implements
|
||||||
|
TelephonyCallback.ActiveDataSubscriptionIdListener {
|
||||||
|
@Override
|
||||||
|
public void onActiveDataSubscriptionIdChanged(int subId) {
|
||||||
|
dlog("onActiveDataSubscriptionIdChanged subId:" + subId);
|
||||||
|
mSubId = subId;
|
||||||
|
update5gState();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final TelephonyCallback mTelephonyCallback = new ActiveDataSubIdCallback();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
dlog("onCreate");
|
||||||
|
mCameraManager = getSystemService(CameraManager.class);
|
||||||
|
mSubManager = getSystemService(SubscriptionManager.class);
|
||||||
|
mTelephonyManager = getSystemService(TelephonyManager.class);
|
||||||
|
|
||||||
|
mCameraManager.registerAvailabilityCallback(mCameraCallback, mHandler);
|
||||||
|
mTelephonyManager.registerTelephonyCallback(mExecutor, mTelephonyCallback);
|
||||||
|
mSubManager.addOnSubscriptionsChangedListener(mExecutor, mSubListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
dlog("onStartCommand");
|
||||||
|
return START_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
dlog("onDestroy");
|
||||||
|
mCameraManager.unregisterAvailabilityCallback(mCameraCallback);
|
||||||
|
mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
|
||||||
|
mSubManager.removeOnSubscriptionsChangedListener(mSubListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startService(Context context) {
|
||||||
|
Log.i(TAG, "Starting service");
|
||||||
|
context.startServiceAsUser(new Intent(context, DubaiCameraService.class),
|
||||||
|
UserHandle.CURRENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update5gState() {
|
||||||
|
if (mSubId == INVALID_SUBSCRIPTION_ID
|
||||||
|
|| mSubManager.getActiveSubscriptionIdList().length <= 0) {
|
||||||
|
dlog("update5gState: Invalid subid or no active subs!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final TelephonyManager tm = mTelephonyManager.createForSubscriptionId(mSubId);
|
||||||
|
// Arguably we should use ALLOWED_NETWORK_TYPES_REASON_POWER here but that's already
|
||||||
|
// used by battery saver, and we are out of other reasons
|
||||||
|
long allowedNetworkTypes = tm.getAllowedNetworkTypesForReason(
|
||||||
|
ALLOWED_NETWORK_TYPES_REASON_CARRIER);
|
||||||
|
final boolean is5gAllowed = (allowedNetworkTypes & NETWORK_TYPE_BITMASK_NR) != 0;
|
||||||
|
dlog("update5gState mIsFrontCamInUse:" + mIsFrontCamInUse + " is5gAllowed:" + is5gAllowed);
|
||||||
|
if (mIsFrontCamInUse && is5gAllowed) {
|
||||||
|
allowedNetworkTypes &= ~NETWORK_TYPE_BITMASK_NR;
|
||||||
|
} else if (!mIsFrontCamInUse && !is5gAllowed) {
|
||||||
|
allowedNetworkTypes |= NETWORK_TYPE_BITMASK_NR;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tm.setAllowedNetworkTypesForReason(ALLOWED_NETWORK_TYPES_REASON_CARRIER,
|
||||||
|
allowedNetworkTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void dlog(String msg) {
|
||||||
|
if (DEBUG) Log.d(TAG, msg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,7 @@ PRODUCT_COPY_FILES += \
|
||||||
|
|
||||||
# Camera
|
# Camera
|
||||||
PRODUCT_PACKAGES += \
|
PRODUCT_PACKAGES += \
|
||||||
|
DubaiCameraService \
|
||||||
libgui_shim_vendor
|
libgui_shim_vendor
|
||||||
|
|
||||||
# Fingerprint
|
# Fingerprint
|
||||||
|
|
Loading…
Reference in a new issue