nx: Import devicesettings from tegra-common 9c7025b
This is a baseline to modify Change-Id: Ifaf5309ec0e2a15626571b667d567bc514082cad
This commit is contained in:
1 parent
1148c4d66d
commit
d088f2f0c3
21 files changed
+910
No files matched your search
@@ -0,0 +1,38 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
LOCAL_CERTIFICATE := platform
|
||||
LOCAL_PRIVATE_PLATFORM_APIS := true
|
||||
LOCAL_PRIVILEGED_MODULE := true
|
||||
LOCAL_PACKAGE_NAME := DeviceSettings
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_USE_AAPT2 := true
|
||||
|
||||
LOCAL_STATIC_ANDROID_LIBRARIES := \
|
||||
androidx.core_core \
|
||||
androidx.preference_preference \
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
org.lineageos.platform.internal \
|
||||
vendor.nvidia.hardware.graphics.display-V1.0-java
|
||||
|
||||
LOCAL_RESOURCE_DIR := \
|
||||
$(LOCAL_PATH)/res \
|
||||
$(TOP)/packages/resources/devicesettings/res
|
||||
|
||||
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
|
||||
|
||||
LOCAL_REQUIRED_MODULES := \
|
||||
privapp-permissions-lineage-displaysettings.xml
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := privapp-permissions-lineage-displaysettings.xml
|
||||
LOCAL_MODULE_CLASS := ETC
|
||||
LOCAL_SRC_FILES := permissions/privapp-permissions-lineage-displaysettings.xml
|
||||
LOCAL_MODULE_RELATIVE_PATH := permissions
|
||||
include $(BUILD_PREBUILT)
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.lineageos.settings.device"
|
||||
android:sharedUserId="android.uid.system">
|
||||
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="28"
|
||||
android:targetSdkVersion="28" />
|
||||
|
||||
<application
|
||||
android:icon="@mipmap/ic_launcher_settings"
|
||||
android:label="@string/device_settings_app_name"
|
||||
android:theme="@style/Theme.Main"
|
||||
android:defaultToDeviceProtectedStorage="true"
|
||||
android:directBootAware="true"
|
||||
android:persistent="true">
|
||||
|
||||
<service android:name=".DisplayService"
|
||||
android:enabled="true"/>
|
||||
|
||||
<receiver android:name=".BootCompletedReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<provider
|
||||
android:name=".DeviceSettingsSearchIndexablesProvider"
|
||||
android:authorities="org.lineageos.settings.device"
|
||||
android:multiprocess="false"
|
||||
android:grantUriPermissions="true"
|
||||
android:permission="android.permission.READ_SEARCH_INDEXABLES"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" />
|
||||
</intent-filter>
|
||||
</provider>
|
||||
|
||||
<activity
|
||||
android:name=".DisplaySettingsActivity"
|
||||
android:label="@string/display_panel_title"
|
||||
android:icon="@drawable/ic_settings_additional_buttons"
|
||||
android:theme="@style/Theme.Main">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.settings.action.IA_SETTINGS" />
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="com.android.settings.category"
|
||||
android:value="com.android.settings.category.ia.system" />
|
||||
<meta-data
|
||||
android:name="com.android.settings.summary"
|
||||
android:resource="@string/display_panel_summary" />
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<permissions>
|
||||
<privapp-permissions package="org.lineageos.settings.device">
|
||||
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
|
||||
</privapp-permissions>
|
||||
</permissions>
|
||||
@@ -0,0 +1,3 @@
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) 2017 The LineageOS 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"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M17,1L7,1C5.9,1,5,1.9,5,3v2h2v4H5v12c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z
|
||||
M11,21H7v-2h4V21z M17,21 h-4v-2h4V21z" />
|
||||
</vector>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2020 The LineageOS 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.
|
||||
-->
|
||||
<resources>
|
||||
<integer name="mode_confirmation_wait_time">15</integer>
|
||||
</resources>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2020 The LineageOS 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.
|
||||
-->
|
||||
<resources>
|
||||
<string name="display_panel_title">Display Configuration</string>
|
||||
<string name="display_panel_summary">Adjust external display and dock settings</string>
|
||||
<string name="mode_selection_title">Select Mode</string>
|
||||
<string name="mode_confirmation_title">Confirmation</string>
|
||||
<string name="mode_confirmation_summary">Are you sure you want to keep these display settings?\n\nWill revert in %1$d seconds</string>
|
||||
<string name="disable_internal_on_external_connected_title">Turn off when an external display is connected</string>
|
||||
<string name="disable_internal_on_external_connected_summary_on">The internal panel will be turned off when an external display is connected</string>
|
||||
<string name="disable_internal_on_external_connected_summary_off">Both the internal panel and external display will show the same image</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014-2016 The CyanogenMod Project
|
||||
(C) 2020 The LineageOS 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.
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<style name="Theme.Main" parent="@android:style/Theme.DeviceDefault.Settings">
|
||||
<item name="dialogPreferenceStyle">@style/Theme.Main.DialogPreferenceStyle</item>
|
||||
<item name="preferenceCategoryStyle">@style/Theme.Main.PreferenceCategoryStyle</item>
|
||||
<item name="preferenceFragmentStyle">@style/Theme.Main.PreferenceFragmentStyle</item>
|
||||
<item name="preferenceStyle">@style/Theme.Main.PreferenceStyle</item>
|
||||
<item name="preferenceTheme">@style/Theme.Main.PreferenceTheme</item>
|
||||
<item name="switchPreferenceStyle">@style/Theme.Main.SwitchPreferenceStyle</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Main.DialogPreferenceStyle" parent="@*android:style/Preference.DeviceDefault.DialogPreference">
|
||||
<item name="allowDividerAbove">false</item>
|
||||
<item name="allowDividerBelow">true</item>
|
||||
<item name="singleLineTitle">false</item>
|
||||
<item name="android:iconSpaceReserved">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Main.PreferenceCategoryStyle" parent="@*android:style/Preference.DeviceDefault.Category">
|
||||
<item name="allowDividerAbove">true</item>
|
||||
<item name="allowDividerBelow">true</item>
|
||||
<item name="android:layout">@layout/preference_category_material_settings</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Main.PreferenceFragmentStyle" parent="@*android:style/PreferenceFragment.Material">
|
||||
<item name="allowDividerAfterLastItem">false</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Main.PreferenceStyle" parent="@*android:style/Preference.DeviceDefault">
|
||||
<item name="allowDividerAbove">false</item>
|
||||
<item name="allowDividerBelow">true</item>
|
||||
<item name="singleLineTitle">false</item>
|
||||
<item name="android:layout">@layout/preference_material_settings</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Main.PreferenceTheme">
|
||||
</style>
|
||||
|
||||
<style name="Theme.Main.SwitchPreferenceStyle" parent="@style/Theme.Main.PreferenceStyle">
|
||||
<item name="widgetLayout">@*android:layout/preference_widget_switch</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2020 The LineageOS 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.
|
||||
-->
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
</PreferenceScreen>
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The LineageOS 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 org.lineageos.settings.device;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class BootCompletedReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
context.startService(new Intent(context, DisplayService.class));
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The LineageOS 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 org.lineageos.settings.device;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.provider.SearchIndexablesProvider;
|
||||
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID;
|
||||
import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
|
||||
import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS;
|
||||
import static android.provider.SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS;
|
||||
|
||||
public class DeviceSettingsSearchIndexablesProvider extends SearchIndexablesProvider {
|
||||
public static final int SEARCH_IDX_BUTTON_PANEL = 0;
|
||||
private static final String TAG = "ConfigPanelSearchIndexablesProvider";
|
||||
private static SearchIndexableResource[] INDEXABLE_RES = new SearchIndexableResource[]{
|
||||
new SearchIndexableResource(1, R.xml.display_panel,
|
||||
DisplaySettingsActivity.class.getName(),
|
||||
R.drawable.ic_settings_additional_buttons),
|
||||
};
|
||||
|
||||
private static Object[] generateResourceRef(SearchIndexableResource sir) {
|
||||
Object[] ref = new Object[7];
|
||||
ref[COLUMN_INDEX_XML_RES_RANK] = sir.rank;
|
||||
ref[COLUMN_INDEX_XML_RES_RESID] = sir.xmlResId;
|
||||
ref[COLUMN_INDEX_XML_RES_CLASS_NAME] = null;
|
||||
ref[COLUMN_INDEX_XML_RES_ICON_RESID] = sir.iconResId;
|
||||
ref[COLUMN_INDEX_XML_RES_INTENT_ACTION] = "com.android.settings.action.EXTRA_SETTINGS";
|
||||
ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE] = "org.lineageos.settings.device";
|
||||
ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = sir.className;
|
||||
return ref;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryXmlResources(String[] projection) {
|
||||
MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
|
||||
cursor.addRow(generateResourceRef(INDEXABLE_RES[SEARCH_IDX_BUTTON_PANEL]));
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryRawData(String[] projection) {
|
||||
MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryNonIndexableKeys(String[] projection) {
|
||||
MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The LineageOS 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 org.lineageos.settings.device;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManagerPolicyConstants;
|
||||
|
||||
public class DisplayService extends Service {
|
||||
private static final String TAG = DisplayService.class.getSimpleName();
|
||||
final Receiver mReceiver = new Receiver();
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
// We don't provide binding, so return null
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
mReceiver.init();
|
||||
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
final class Receiver extends BroadcastReceiver {
|
||||
private boolean mExternalDisplayConnected = false;
|
||||
|
||||
public void init() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
|
||||
filter.addAction(WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED);
|
||||
filter.addAction(Intent.ACTION_SCREEN_ON);
|
||||
|
||||
registerReceiver(this, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
SharedPreferences sharedPrefs = context.getSharedPreferences("org.lineageos.settings.device_preferences", context.MODE_PRIVATE);
|
||||
Log.w(TAG, intent.getAction());
|
||||
String action = intent.getAction();
|
||||
|
||||
switch (action) {
|
||||
case WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED:
|
||||
mExternalDisplayConnected = intent.getBooleanExtra(WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE, false);
|
||||
case Intent.ACTION_SCREEN_ON:
|
||||
DisplayUtils.setInternalDisplayState(!(mExternalDisplayConnected && sharedPrefs.getBoolean("disable_internal_on_external_connected", false)));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The LineageOS 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 org.lineageos.settings.device;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.view.WindowManagerPolicyConstants;
|
||||
|
||||
|
||||
public class DisplaySettingsActivity extends PreferenceActivity {
|
||||
public final Receiver mReceiver = new Receiver();
|
||||
private DisplaySettingsFragment mFragment;
|
||||
public boolean mExternalDisplayConnected;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mFragment = new DisplaySettingsFragment();
|
||||
|
||||
getFragmentManager().beginTransaction().replace(android.R.id.content, mFragment).commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mReceiver.init(this);
|
||||
}
|
||||
|
||||
final class Receiver extends BroadcastReceiver {
|
||||
private boolean mReceivedInitialIntent = false;
|
||||
public boolean mBlocked;
|
||||
|
||||
public void init(Context context) {
|
||||
// Refresh UI on external display status change
|
||||
IntentFilter filter = new IntentFilter();
|
||||
|
||||
filter.addAction(WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED);
|
||||
|
||||
mReceivedInitialIntent = false;
|
||||
context.registerReceiver(this, filter);
|
||||
}
|
||||
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
mExternalDisplayConnected = intent.getBooleanExtra(WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE, false);
|
||||
|
||||
if (mBlocked)
|
||||
return;
|
||||
|
||||
if (mReceivedInitialIntent)
|
||||
recreate();
|
||||
|
||||
mReceivedInitialIntent = true;
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The LineageOS 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 org.lineageos.settings.device;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceFragment;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.HwcSvcDisplay;
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.HwcSvcDisplayMode;
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.HwcSvcDisplayType;
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.HwcSvcModeType;
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.INvDisplay;
|
||||
|
||||
public class DisplaySettingsFragment extends PreferenceFragment
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = DisplaySettingsFragment.class.getSimpleName();
|
||||
public boolean mInModeChange = false;
|
||||
private INvDisplay mDisplayService;
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
try {
|
||||
mDisplayService = INvDisplay.getService(true /* retry */);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
|
||||
addPreferencesFromResource(R.xml.display_panel);
|
||||
PreferenceScreen preferenceScreen = this.getPreferenceScreen();
|
||||
|
||||
for (int i = HwcSvcDisplay.HWC_SVC_DISPLAY_PANEL; i <= HwcSvcDisplay.HWC_SVC_DISPLAY_HDMI2; i++) {
|
||||
PreferenceCategory category = new PreferenceCategory(preferenceScreen.getContext());
|
||||
|
||||
if (!initializeDisplayCategory(category, i))
|
||||
continue;
|
||||
|
||||
preferenceScreen.addPreference(category);
|
||||
populateDisplayCategory(category, i);
|
||||
|
||||
}
|
||||
|
||||
final ActionBar actionBar = getActivity().getActionBar();
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
prefs.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
prefs.unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
getActivity().onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPrefs, String key) {
|
||||
HashMap<String, Integer> uidMap = DisplayUtils.makeUidMap(mDisplayService);
|
||||
if (key.startsWith("mode_")) {
|
||||
String hash = key.substring(5);
|
||||
int display = uidMap.getOrDefault(hash, -1);
|
||||
|
||||
if (display >= 0) {
|
||||
int modeIndex = Integer.valueOf(sharedPrefs.getString(key, ""));
|
||||
((DisplaySettingsActivity)getActivity()).mReceiver.mBlocked = true;
|
||||
performModeChange(sharedPrefs, key, modeIndex, display);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.equals("disable_internal_on_external_connected")) {
|
||||
DisplayUtils.setInternalDisplayState(!(((DisplaySettingsActivity)getActivity()).mExternalDisplayConnected && sharedPrefs.getBoolean(key, false)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void performModeChange(SharedPreferences sharedPrefs, String key, int modeIndex, int display) {
|
||||
try {
|
||||
mDisplayService.modeDefaultSetIndex(display, modeIndex);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to set default display mode");
|
||||
return;
|
||||
}
|
||||
|
||||
DialogInterface.OnClickListener confirmationDialogClickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
try {
|
||||
mDisplayService.modeDefaultCommit(display);
|
||||
mDisplayService.modeDefaultStore(display);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to save default display mode");;
|
||||
}
|
||||
break;
|
||||
|
||||
case DialogInterface.BUTTON_NEGATIVE:
|
||||
try {
|
||||
mDisplayService.modeDefaultRollback(display);
|
||||
mDisplayService.modeUpdate(display);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to rollback display mode");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
HwcSvcDisplayMode currentMode;
|
||||
|
||||
try {
|
||||
currentMode = mDisplayService.getMode(display, HwcSvcModeType.HWC_SVC_MODE_TYPE_CURRENT);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to read display mode");
|
||||
((DisplaySettingsActivity)getActivity()).mReceiver.mBlocked = false;
|
||||
getActivity().recreate();
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPreferences.Editor editor = sharedPrefs.edit();
|
||||
editor.putString(key, String.valueOf(currentMode.index));
|
||||
editor.commit();
|
||||
((DisplaySettingsActivity)getActivity()).mReceiver.mBlocked = false;
|
||||
getActivity().recreate();
|
||||
}
|
||||
};
|
||||
|
||||
int waitTime = getResources().getInteger(R.integer.mode_confirmation_wait_time);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getView().getContext());
|
||||
builder.setTitle(R.string.mode_confirmation_title)
|
||||
.setPositiveButton(android.R.string.ok, confirmationDialogClickListener)
|
||||
.setNegativeButton(android.R.string.cancel, confirmationDialogClickListener)
|
||||
.setMessage(getString(R.string.mode_confirmation_summary, waitTime));
|
||||
|
||||
AlertDialog confirmationDialog = builder.create();
|
||||
confirmationDialog.show();
|
||||
|
||||
new CountDownTimer(waitTime * 1000, 1000) {
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
if (confirmationDialog != null && isAdded())
|
||||
confirmationDialog.setMessage(getString(R.string.mode_confirmation_summary, millisUntilFinished / 1000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
if (confirmationDialog != null && isAdded())
|
||||
confirmationDialog.getButton(DialogInterface.BUTTON_NEGATIVE).performClick();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private boolean initializeDisplayCategory(PreferenceCategory category, int display) {
|
||||
try {
|
||||
int type = mDisplayService.displayGetType(display);
|
||||
ArrayList<HwcSvcDisplayMode> availableModes = mDisplayService.modeGetList(display);
|
||||
|
||||
if (availableModes.size() == 0)
|
||||
return false; // Display is not connected
|
||||
|
||||
category.setTitle(DisplayUtils.makeDisplayLabel(mDisplayService.edidGetInfo(display), display));
|
||||
category.setSummary(HwcSvcDisplayType.toString(type));
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to read display info");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void populateDisplayCategory(PreferenceCategory category, int display) {
|
||||
String displayUid;
|
||||
HwcSvcDisplayMode currentMode;
|
||||
ArrayList<HwcSvcDisplayMode> availableModes;
|
||||
|
||||
try {
|
||||
displayUid = String.valueOf(DisplayUtils.makeDisplayLabel(mDisplayService.edidGetInfo(display), display).hashCode());
|
||||
currentMode = mDisplayService.getMode(display, HwcSvcModeType.HWC_SVC_MODE_TYPE_CURRENT);
|
||||
availableModes = mDisplayService.modeGetList(display);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to read display info");
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort by resolution and refresh rate
|
||||
Collections.sort(availableModes, new Comparator() {
|
||||
public int compare(Object a, Object b) {
|
||||
HwcSvcDisplayMode modeA = (HwcSvcDisplayMode) a;
|
||||
HwcSvcDisplayMode modeB = (HwcSvcDisplayMode) b;
|
||||
|
||||
if (modeA.xres == modeB.xres) {
|
||||
if (modeA.yres == modeB.yres) {
|
||||
if (modeA.refresh == modeB.refresh)
|
||||
return 0;
|
||||
else if (modeA.refresh > modeB.refresh)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
} else if (modeA.yres > modeB.yres) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if (modeA.xres > modeB.xres) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ListPreference modesPreference = new ListPreference(category.getContext());
|
||||
ArrayList<String> displayedModes = new ArrayList<String>();
|
||||
ArrayList<String> modeIndices = new ArrayList<String>();
|
||||
|
||||
availableModes.forEach((mode) -> displayedModes.add(DisplayUtils.makeModeInfoString(mode) + " " + DisplayUtils.makeColorInfoString(mode)));
|
||||
availableModes.forEach((mode) -> modeIndices.add(String.valueOf(mode.index)));
|
||||
|
||||
modesPreference.setEntries(displayedModes.toArray(new CharSequence[displayedModes.size()]));
|
||||
modesPreference.setEntryValues(modeIndices.toArray(new CharSequence[modeIndices.size()]));
|
||||
modesPreference.setTitle(R.string.mode_selection_title);
|
||||
modesPreference.setSummary(DisplayUtils.makeModeInfoString(currentMode) + "\n" + DisplayUtils.makeColorInfoString(currentMode));
|
||||
modesPreference.setKey("mode_" + displayUid);
|
||||
modesPreference.setValue(String.valueOf(currentMode.index));
|
||||
|
||||
category.addPreference(modesPreference);
|
||||
|
||||
// Show checkbox to disable internal panel when an external display is connected
|
||||
if (display == HwcSvcDisplay.HWC_SVC_DISPLAY_PANEL) {
|
||||
SwitchPreference disableInternalOnExternalConnectedPreference = new SwitchPreference(category.getContext());
|
||||
disableInternalOnExternalConnectedPreference.setTitle(R.string.disable_internal_on_external_connected_title);
|
||||
disableInternalOnExternalConnectedPreference.setSummaryOn(R.string.disable_internal_on_external_connected_summary_on);
|
||||
disableInternalOnExternalConnectedPreference.setSummaryOff(R.string.disable_internal_on_external_connected_summary_off);
|
||||
disableInternalOnExternalConnectedPreference.setKey("disable_internal_on_external_connected");
|
||||
|
||||
category.addPreference(disableInternalOnExternalConnectedPreference);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The LineageOS 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 org.lineageos.settings.device;
|
||||
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.HwcSvcDisplay;
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.HwcSvcDisplayMode;
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.HwcSvcDisplayModePixEnc;
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.HwcSvcEdidInfo;
|
||||
import vendor.nvidia.hardware.graphics.display.V1_0.INvDisplay;
|
||||
|
||||
public class DisplayUtils {
|
||||
private static final String TAG = DisplayUtils.class.getSimpleName();
|
||||
|
||||
public static void setInternalDisplayState(boolean state) {
|
||||
Log.d(TAG, "setInternalDisplayState: " + String.valueOf(state));
|
||||
try {
|
||||
FileOutputStream enableFile = new FileOutputStream("/sys/bus/platform/devices/tegradc.0/enable");
|
||||
byte[] buf = new byte[2];
|
||||
|
||||
buf[0] = (byte) (state ? '1' : '0');
|
||||
buf[1] = '\n';
|
||||
|
||||
enableFile.write(buf);
|
||||
enableFile.close();
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Failed to write display state");
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<String, Integer> makeUidMap(INvDisplay displayService) {
|
||||
HashMap<String, Integer> uidMap = new HashMap<String, Integer>();
|
||||
for (int i = HwcSvcDisplay.HWC_SVC_DISPLAY_PANEL; i <= HwcSvcDisplay.HWC_SVC_DISPLAY_HDMI2; i++) {
|
||||
try {
|
||||
String displayUid = String.valueOf(makeDisplayLabel(displayService.edidGetInfo(i), i).hashCode()); // A unique id we can use to identify the display
|
||||
uidMap.put(displayUid, i);
|
||||
} catch (RemoteException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return uidMap;
|
||||
}
|
||||
|
||||
public static String makeDisplayLabel(HwcSvcEdidInfo edid, int display) {
|
||||
if (!edid.monitor_name.isEmpty())
|
||||
return (edid.manufacturer_id.isEmpty() ? "" : (edid.manufacturer_id + " - ")) + edid.monitor_name; // Report name from edid if present
|
||||
if (display == HwcSvcDisplay.HWC_SVC_DISPLAY_PANEL)
|
||||
return "Internal Panel"; // Most internal panels do not have an edid
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
public static String makeModeInfoString(HwcSvcDisplayMode mode) {
|
||||
return String.format("%dx%d %sHz", mode.xres, mode.yres, new DecimalFormat("###.##").format(mode.refresh));
|
||||
}
|
||||
|
||||
public static String makeColorInfoString(HwcSvcDisplayMode mode) {
|
||||
String encodingStr = "";
|
||||
String colorimetryStr = "";
|
||||
|
||||
switch (mode.pixenc) {
|
||||
case HwcSvcDisplayModePixEnc.HWC_SVC_DISP_PIXENC_YUV444:
|
||||
encodingStr = "YUV444";
|
||||
break;
|
||||
case HwcSvcDisplayModePixEnc.HWC_SVC_DISP_PIXENC_YUV422:
|
||||
encodingStr = "YUV422";
|
||||
break;
|
||||
case HwcSvcDisplayModePixEnc.HWC_SVC_DISP_PIXENC_YUV420:
|
||||
encodingStr = "YUV420";
|
||||
break;
|
||||
default:
|
||||
encodingStr = "RGB";
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode.colorimetry != 1)
|
||||
colorimetryStr = "Rec. 709";
|
||||
else
|
||||
colorimetryStr = "Rec. 2020";
|
||||
|
||||
return String.format("%s %d-bit %s", encodingStr, mode.bpc, colorimetryStr);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user