android_mt6572_jiabo/lineage/wiki/pages/devices.html
2025-09-05 16:56:03 +08:00

562 lines
20 KiB
HTML

---
layout: default
title: Devices
permalink: devices/
redirect_from: devices.html
search: exclude
---
<script type="text/javascript">
const DEVICES = JSON.parse(
decodeURIComponent('{{ site.data.devices | jsonify | url_encode }}'.replaceAll('+', ' '))
);
$(window).on('load', applyFilters);
function applyFilters() {
const checkBoxValue = (filter) =>
$(`div[data-filter=${filter}] input[type=checkbox]`)
.is(":checked");
const checkBoxValues = (filter) =>
[...$(`div[data-filter=${filter}] input[type=checkbox]:checked`)]
.map((e) => e.getAttribute("data-value"));
const radioValue = (filter) =>
parseFloat($(`div[data-filter=${filter}] input[type=radio]:checked`).val());
const rangeValue = (filter) =>
parseFloat($(`div[data-filter=${filter}] input[type=range]`).val());
let filters = [
// Global :: Show discontinued devices
(device) => {
let value = checkBoxValue("maintainers");
return !value || device.maintainers.length > 0;
},
// Global :: Show devices without official BL unlock method
(device) => {
let value = checkBoxValue("is_unlockable");
return !value || device.is_unlockable !== false;
},
// Architecture
(device) => {
let value = checkBoxValues("architectures");
let cpu = device.architecture.cpu ?? device.architecture;
return value.length === 0 || value.some(x => cpu === x);
},
// SoC vendor
(device) => {
let value = checkBoxValues("soc_vendors");
return value.length === 0 || value.some(x => device.soc.includes(x));
},
// Device type
(device) => {
let value = checkBoxValues("types");
return value.length === 0 || value.some(x => device.type.includes(x));
},
// Networks
(device) => {
let value = checkBoxValues("networks");
return value.length === 0 || value.every(x => device.network.includes(x));
},
// Wi-Fi
(device) => {
let value = checkBoxValues("wifi");
return value.length === 0 || value.some(x => device.wifi.includes(x));
},
// Peripherals
(device) => {
let value = checkBoxValues("peripherals");
return value.length === 0 || value.every(x => device.peripherals.includes(x));
},
// SDCard slot
(device) => {
let value = radioValue("sdcard");
return value === 0 || device.sdcard !== undefined;
},
// Min screen size in inches
(device) => {
let value = rangeValue("screen-size-min");
let size = device.screen.size ?? 0;
return value === 0 || (size > 0 && size >= value);
},
// Max screen size in inches
(device) => {
let value = rangeValue("screen-size-max");
let size = device.screen.size ?? 0;
return value === 0 || (size > 0 && size <= value);
},
// Min release year
(device) => {
let value = rangeValue("release");
let years = typeof(device.release) === "object"
? device.release.map(x => parseInt(Object.values(x).toString().substring(0, 4)))
: [ parseInt(device.release.toString().substring(0, 4)) ];
return years.some(x => x >= value);
},
// LineageOS versions
(device) => {
let value = checkBoxValues("versions").map((x) => parseFloat(x));
return value.length === 0 || value.some(x => device.versions.includes(x));
},
// Kernel versions
(device) => {
let value = checkBoxValues("kernel_versions");
return value.length === 0 || value.some(x => device.kernel.version.includes(x));
},
];
// Hide devices not matching filters
$(".devices .item").each(function () {
let codename = $(this).attr("data-codename");
if (codename === undefined) {
$(this).addClass("hidden");
return;
}
let variant = $(this).attr("data-variant");
if (variant.length > 0) {
codename += `_variant${$(this).attr("data-variant")}`;
}
if (filters.every(x => x(DEVICES[codename]))) {
$(this).removeClass("hidden");
$(this).parent().show();
} else {
$(this).addClass("hidden");
}
})
// Hide empty vendors
$(".devices").each(function() {
$(`*[data-vendor="${$(this).attr("data-vendor")}"]`)
.toggle($(this).find("div:visible").length > 1);
if ($(`*[data-vendor="${$(this).attr("data-vendor")}"]`).find("div:visible").length > 1) {
$(this).find(`*[data-variant="unknown"]`).removeClass("hidden");
}
});
// Hide vendors list
$("#vendor-list").toggle($(".devices:visible").length > 1);
// Show empty list placeholder
$("#empty-list").toggle($(".devices:visible").length === 0);
// Update number of devices found
$("#filtered-devices").text(`${$(".devices .item:visible[data-variant!=unknown]").length}`);
$("#total-devices").text(`${$(".devices .item[data-variant!=unknown]").length}`);
}
function closeFilters() {
$("#popup-filters").trigger("close");
applyFilters();
}
function showFilters() {
$("#popup-filters").trigger("open");
}
</script>
<div class="container page">
<h1>{{ page.title }}</h1>
Devices with a lower opacity image are no longer officially supported and the pages exist for reference only.<br/>
You can show them by disabling "Hide discontinued devices" in the device filters below:<br/><br/>
{%- assign devices = "" | split: " " %}
{%- assign variants = "" | split: " " %}
{%- for device in site.data.devices %}
{%- assign data = device[1] %}
{%- if data.variant == None or data.variant == 1 %}
{%- assign devices = devices | push: data %}
{%- elsif data.variant %}
{%- assign variants = variants | push: data %}
{%- endif %}
{%- endfor %}
{%- assign sorted = devices | sort_natural: 'name' | sort_natural: 'vendor' %}
{%- assign lastVendor = "" %}
<div class="form-check form-check-inline">
<button onclick="showFilters()" class="btn btn-primary" aria-label="Filter devices">Filter (<span id="filtered-devices">0</span> of <span id="total-devices">0</span> shown)</button>
</div><br/><br/>
<div id="vendor-list">
Select a vendor to jump to:<br/>
<div class="vendor-container">
{%- assign vendors = "" | split: " " %}
{%- for device in sorted %}
{%- if device.vendor != lastVendor %}
{%- assign vendors = vendors | push: device.vendor %}
{%- assign lastVendor = device.vendor %}
<div data-vendor="{{ lastVendor | slugify }}"><a href="#{{ lastVendor | slugify }}" data-vendor="{{ lastVendor | slugify }}">{{ lastVendor }}</a></div>
{%- endif %}
{%- endfor %}
</div>
</div>
<div id="empty-list" style="display: none">
No devices matching selected filters!
</div>
{%- for device in sorted %}
{%- if device.vendor != lastVendor %}
{%- assign lastVendor = device.vendor %}
{% capture vendorId %}{{ device.vendor | slugify }}{% endcapture %}
<h2 class="h2" id="{{ vendorId }}" data-vendor="{{ vendorId }}">{{ device.vendor}}</h2>
<a href="#devices" class="top" data-vendor="{{ vendorId }}"><i class="material-icons">arrow_drop_up</i>Top</a>
<div class="devices" data-vendor="{{ vendorId }}">
{%- endif %}
{%- assign url = "devices/" | append: device.codename | append: "/" | relative_url %}
{%- if device.maintainers == empty %}
{%- assign class="discontinued hidden" %}
{%- else %}
{%- assign class="" %}
{%- endif -%}
<div class="item {{ class }}" onClick="location.href='{{ url }}'" data-codename="{{ device.codename }}" data-variant="{{ device.variant }}" data-url="{{ url }}">
<div class="deviceimage">
<a href="{{ url }}"><img src="{{ "images/devices/small/" | append: device.image | relative_url }}" alt="device-image for {{ device.codename }}" loading="lazy" /></a>
</div>
<div class="name">
<a href="{{ url }}">
{%- include snippets/get_displayname.md device=device %}
<span class="devicename">{{ display_name }}</span>
</a><br>
{%- if device.variant %}
<div class="variant-container">
<span class="aka">AKA</span>
{%- assign device_variants = "" | split: " " %}
{%- assign sorted_variants = variants | sort_natural: 'variant' %}
{%- for variant in sorted_variants %}
{%- if variant.codename == device.codename %}
{%- assign device_variants = device_variants | push: variant %}
{%- endif %}
{%- endfor %}
{%- for variant in device_variants %}
{%- include snippets/get_displayname.md device=variant %}
<span class="variant"><a href="{{ url }}">{{ display_name }}</a></span>
{%- unless forloop.last %}
<span class="bullet"></span>
{%- endunless %}
{%- endfor %}
</div>
<div class="variants-list">
<ul>
{%- assign variant_url = "devices/" | append: device.codename | append: "/variant1/"| relative_url %}
{%- include snippets/get_displayname.md device=device %}
<li onClick="location.href='{{ variant_url }}'"><a href="{{ variant_url }}">{{ display_name }}</a></li>
{%- for variant in device_variants %}
{%- assign variant_url = "devices/" | append: variant.codename | append: "/variant" | append: variant.variant | append: "/" | relative_url %}
{%- include snippets/get_displayname.md device=variant %}
<li onClick="location.href='{{ variant_url }}'"><a href="{{ variant_url }}">{{ display_name }}</a></li>
{%- endfor %}
</ul>
</div>
{%- endif %}
<a href="{{ url }}">
<span class="codename">{{ device.codename }}</span>
</a>
</div>
</div>
{%- if sorted[forloop.index].vendor != lastVendor %}
{%- assign url = "devices/unknown/" | relative_url %}
<div class="item" onClick="location.href='{{ url }}'" data-variant="unknown" data-url="{{ url }}">
<div class="deviceimage">
<a href="{{ url }}"><img src="{{ "images/devices/small/unknown.png" | relative_url }}" alt="unknown device" loading="lazy" /></a>
</div>
<div class="name">
<a href="{{ url }}">
<span class="devicename">Other model</span>
</a><br>
<a href="{{ url }}">
<span class="codename">Other codename</span>
</a>
</div>
</div>
</div> <!-- div class="devices" -->
{% endif %}
{%- endfor %}
</div>
{%- assign definitions = site.data.schema.definitions %}
{%- assign properties = site.data.schema.properties %}
<div class="page-overlay" id="popup-filters">
<div class="popup-overlay" style="min-width: 400px">
<div class="popup-content">
<div class="popup-close-action"><span class="material-icons close-action">close</span></div>
<div class="popup-header" style="height: auto">
<span class="popup-title">Device filters</span><br/>
</div>
<div class="popup-body" style="max-height: 500px; overscroll-behavior: contain; overflow-y: auto">
<p class="device-filters-header">Global:</p>
<div class="form-check" data-filter="maintainers">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox" checked>
Hide discontinued devices
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
<div class="form-check" data-filter="is_unlockable">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox">
Hide devices without official BL unlock method
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
<p class="device-filters-header">Architecture:</p>
{% for value in definitions.valid_architectures.enum %}
<div class="form-check" data-filter="architectures">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox" data-value="{{ value }}">
{{ value }}
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
{% endfor %}
<p class="device-filters-header">SoC vendor:</p>
{% for value in site.data.device_filters.soc_vendors %}
<div class="form-check" data-filter="soc_vendors">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox" data-value="{{ value }}">
{{ value }}
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
{% endfor %}
<p class="device-filters-header">Device type:</p>
{% for value in properties.type.enum %}
<div class="form-check" data-filter="types">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox" data-value="{{ value }}">
{{ value | capitalize }}
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
{% endfor %}
<p class="device-filters-header">Networks:</p>
{% for value in definitions.valid_networks.items.enum %}
<div class="form-check" data-filter="networks">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox" data-value="{{ value }}">
{{ value }}
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
{% endfor %}
<p class="device-filters-header">Wi-Fi:</p>
{% assign wifi_values = properties.wifi.enum | shift %}
{% for value in wifi_values %}
<div class="form-check" data-filter="wifi">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox" data-value="{{ value }}">
{{ value }}
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
{% endfor %}
<p class="device-filters-header">Peripherals:</p>
{% for value in definitions.valid_peripherals.items.enum %}
<div class="form-check" data-filter="peripherals">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox" data-value="{{ value }}">
{{ value }}
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
{% endfor %}
<p class="device-filters-header">SD card slot:</p>
<div class="form-check" data-filter="sdcard">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="device-filter-sdcard" value="0" checked />
No
<span class="circle no-ripple">
<span class="check" />
</span>
</label>
</div>
<div class="form-check" data-filter="sdcard">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="device-filter-sdcard" value="1" />
Yes
<span class="circle no-ripple">
<span class="check" />
</span>
</label>
</div>
<p class="device-filters-header">Min screen size in inches:</p>
<div data-filter="screen-size-min">
<input type="range" min="0" max="13" step="0.1" value="0" />
<label />
</div>
<p class="device-filters-header">Max screen size in inches:</p>
<div data-filter="screen-size-max">
<input type="range" min="0" max="13" step="0.1" value="0" />
<label />
</div>
<p class="device-filters-header">Min release year:</p>
<div data-filter="release">
<input type="range" min="2010" value="2010" />
<label />
</div>
<p class="device-filters-header">LineageOS versions:</p>
{% for value in definitions.valid_branches.enum %}
<div class="form-check" data-filter="versions">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox" data-value="{{ value }}">
{{ value }}
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
{% endfor %}
<p class="device-filters-header">Kernel versions:</p>
{% for value in definitions.valid_kernel_versions.enum %}
<div class="form-check" data-filter="kernel_versions">
<label class="form-check-label">
<input class="form-check-input no-ripple" type="checkbox" data-value="{{ value }}">
{{ value }}
<span class="form-check-sign no-ripple">
<span class="check" />
</span>
</label>
</div>
{% endfor %}
</div>
<button onclick="closeFilters()" class="btn btn-primary">Apply</button>
</div>
</div>
</div>
<div class="page-overlay" id="popup-variants">
<div class="popup-overlay">
<div class="popup-content">
<div class="popup-close-action"><span class="material-icons close-action">close</span></div>
<div class="popup-header">
<span class="popup-title">Select your variant</span><br/>
<span class="popup-subtitle">codename</span>
</div>
<div class="popup-body">
<p>
These devices all use the same LineageOS build.
The vendor may have released the same device under multiple names, or the maintainer may support multiple devices using the same code.
</p>
<p style="margin-bottom: 0px;">
Select your variant to make sure your guides are correct. Not sure which?<br/>
<a href="" id="compare-link">Compare their differences.</a>
</p>
<div class="popup-variants-list"></div>
</div>
</div>
</div>
</div>
<script>
// Handle page overlay click and close events
$('.page-overlay').on('click close', function() {
$(this).addClass('closed');
$('html, body').css({
overflow: 'auto',
height: 'auto'
});
});
// Handle page overlay open event
$('.page-overlay').on('open', function() {
$(this).addClass('active').removeClass('closed');
$('html, body').css({
overflow: 'hidden',
});
});
// Close the popup
$('.popup-close-action').on('click', function() {
$(this).parents('.page-overlay').trigger('close');
});
// Prevent popup close when clicking on the popup itself
$('.popup-overlay').on('click', function(e) {
e.stopPropagation();
});
// Select all items where variant is set
$('*[data-variant=1]').each(function () {
// remove current onClick target, we do something better
$(this).attr('onclick', '').unbind('click');
$(this).on('click', function() {
codename = $(this).attr('data-codename');
$('#popup-variants').trigger('open');
// Replace relevant parts of dialog content
$('#popup-variants .popup-variants-list').html($(this).find('.variants-list').html());
$('#popup-variants .popup-subtitle').text(codename);
$('#compare-link').attr('href', $(this).attr('data-url'));
// don't remember last scroll position, always start at top
$('#popup-variants .popup-body').scrollTop(0);
});
// Remove current click targets, they are just there as fallback solution
$(this).find('a').each(function() {
$(this).click(function(e){
e.preventDefault();
});
});
// Screen size sliders
$('div[data-filter*=screen-size-] input').on('input', function() {
$(this).siblings('label').text(parseFloat($(this).val()) || "Unset");
});
$('div[data-filter*=screen-size-] input').trigger('input');
// Release year slider
$('div[data-filter=release] input').attr('max', new Date().getFullYear());
$('div[data-filter=release] input').on('input', function() {
$('div[data-filter=release] label').text($(this).val());
});
$('div[data-filter=release] input').trigger('input');
});
</script>