1.Dream
就是常说的屏保,根据图片简单说明下
- 第一个是切换按钮是屏保开关
- 下边5个是屏保程序
- when to start 字面意思,屏保启动的条件
1.1.display_settings
来源 display_settings.xml
<Preference
android:key="screensaver"
android:title="@string/screensaver_settings_title"
android:fragment="com.android.settings.dream.DreamSettings"
settings:keywords="@string/keywords_screensaver"
settings:controller="com.android.settings.display.ScreenSaverPreferenceController"/>
2.DreamSettings.java
屏保程序相关
2.1.dream_fragment_overview.xml
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="screensaver_settings_screen"
android:title="@string/screensaver_settings_title"
settings:keywords="@string/keywords_screensaver">
<!--屏保开关-->
<com.android.settingslib.widget.MainSwitchPreference
android:key="dream_main_settings_switch"
android:title="@string/screensaver_settings_toggle_title"
settings:controller="com.android.settings.dream.DreamMainSwitchPreferenceController"
settings:searchable="false"/>
<!--设置屏保触发的条件,点击进入小节3-->
<Preference
android:key="when_to_start"
android:title="@string/screensaver_settings_when_to_dream"
android:fragment="com.android.settings.dream.WhenToDreamPicker"/>
<PreferenceCategory
android:title="@string/dream_picker_category">
<!--屏保程序选择列表-->
<com.android.settingslib.widget.LayoutPreference
android:key="dream_picker"
android:selectable="false"
android:layout="@layout/dream_picker_layout"
settings:controller="com.android.settings.dream.DreamPickerController"/>
</PreferenceCategory>
<!--好像没用到-->
<SwitchPreference
android:key="dream_complications_toggle"
android:title="@string/dream_complications_toggle_title"
android:summary="@string/dream_complications_toggle_summary"
settings:controller="com.android.settings.dream.DreamComplicationPreferenceController"/>
<com.android.settings.applications.SpacePreference
android:layout_height="16dp" />
</PreferenceScreen>
>dream_picker_layout.xml
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/dream_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:clipToPadding="true"
android:nestedScrollingEnabled="false"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="@dimen/dream_preference_card_padding"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
2.2.onCreate
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final DreamBackend dreamBackend = DreamBackend.getInstance(getContext());
mMainSwitchPreference = findPreference(MAIN_SWITCH_PREF_KEY);
if (mMainSwitchPreference != null) {
mMainSwitchPreference.addOnSwitchChangeListener(this);
}
//如果屏保开关关闭的话,其他的选项也不能操作
setAllPreferencesEnabled(dreamBackend.isEnabled());
}
>onSwitchChanged
public void onSwitchChanged(Switch switchView, boolean isChecked) {
//同步修改其他选项的是否可用
setAllPreferencesEnabled(isChecked);
//预览按钮是否可见
mPreviewButton.setVisibility(isChecked ? View.VISIBLE : View.GONE);
updatePaddingForPreviewButton();
}
>updatePaddingForPreviewButton
和底部有个间隔
private void updatePaddingForPreviewButton() {
mPreviewButton.post(() -> {
mRecyclerView.setPadding(0, 0, 0, mPreviewButton.getMeasuredHeight());
});
}
2.3.getSummaryTextWithDreamName
获取summary,给外部的选项用
public static CharSequence getSummaryTextWithDreamName(Context context) {
DreamBackend backend = DreamBackend.getInstance(context);
return getSummaryTextFromBackend(backend, context);
}
static CharSequence getSummaryTextFromBackend(DreamBackend backend, Context context) {
if (backend.isEnabled()) {
return context.getString(R.string.screensaver_settings_summary_on,// On/%s
backend.getActiveDreamName());// 见 4.3
} else {
return context.getString(R.string.screensaver_settings_summary_off);//Off
}
}
2.4.onCreateRecyclerView
public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
Bundle bundle) {
final DreamBackend dreamBackend = DreamBackend.getInstance(getContext());
final ViewGroup root = getActivity().findViewById(android.R.id.content);
//预览按钮是在这里手动添加的
mPreviewButton = (Button) getActivity().getLayoutInflater().inflate(
R.layout.dream_preview_button, root, false);
mPreviewButton.setVisibility(dreamBackend.isEnabled() ? View.VISIBLE : View.GONE);
root.addView(mPreviewButton);
mPreviewButton.setOnClickListener(v -> dreamBackend.preview(dreamBackend.getActiveDream()));
mRecyclerView = super.onCreateRecyclerView(inflater, parent, bundle);
updatePaddingForPreviewButton();
return mRecyclerView;
}
2.5.key转换
DreamBackend用的key是int,这里选项用的key是string,所以需要转化下
static int getSettingFromPrefKey(String key) {
switch (key) {
case WHILE_CHARGING_ONLY:
return WHILE_CHARGING;
case WHILE_DOCKED_ONLY:
return WHILE_DOCKED;
case EITHER_CHARGING_OR_DOCKED:
return EITHER;
case NEVER_DREAM:
default:
return NEVER;
}
}
static String getKeyFromSetting(@WhenToDream int dreamSetting) {
switch (dreamSetting) {
case WHILE_CHARGING:
return WHILE_CHARGING_ONLY;
case WHILE_DOCKED:
return WHILE_DOCKED_ONLY;
case EITHER:
return EITHER_CHARGING_OR_DOCKED;
case NEVER:
default:
return NEVER_DREAM;
}
}
2.5.DreamPickerController
>getAvailabilityStatus
public DreamPickerController(Context context, String key, DreamBackend backend) {
super(context, key);
mBackend = backend;
//可用的屏保集合
mDreamInfos = mBackend.getDreamInfos();
//选中的屏保
mActiveDream = getActiveDreamInfo(mDreamInfos);
}
@Override
public int getAvailabilityStatus() {
//可用屏保的个数大于0
return mDreamInfos.size() > 0 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
>displayPreference
设置adapter
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mAdapter = new DreamAdapter(R.layout.dream_preference_layout,
mDreamInfos.stream()
.map(DreamItem::new)
.collect(Collectors.toList()));
mAdapter.setEnabled(mBackend.isEnabled());
final LayoutPreference pref = screen.findPreference(getPreferenceKey());
if (pref == null) {
return;
}
final RecyclerView recyclerView = pref.findViewById(R.id.dream_list);
recyclerView.setLayoutManager(new AutoFitGridLayoutManager(mContext));
recyclerView.addItemDecoration(
new GridSpacingItemDecoration(mContext, R.dimen.dream_preference_card_padding));
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(mAdapter);
}
>onItemClicked
private class DreamItem implements IDreamItem {
public void onItemClicked() {
mActiveDream = mDreamInfo;
mBackend.setActiveDream(mDreamInfo.componentName);
}
2.6.DreamMainSwitchPreferenceController.java
屏保开关的控制,最终交给DreamBackend处理
public class DreamMainSwitchPreferenceController extends
SettingsMainSwitchPreferenceController implements LifecycleObserver {
static final String MAIN_SWITCH_PREF_KEY = "dream_main_settings_switch";
public DreamMainSwitchPreferenceController(Context context, String key) {
super(context, key);
mBackend = DreamBackend.getInstance(context);
}
>isChecked
见 4.1
public boolean isChecked() {
return mBackend.isEnabled();
}
public boolean setChecked(boolean isChecked) {
mBackend.setEnabled(isChecked);
return true;
}
>onStart
void onStart() {
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.SCREENSAVER_ENABLED),
/* notifyForDescendants= */ false, mObserver);
}
3.WhenToDreamPicker.java
public class WhenToDreamPicker extends RadioButtonPickerFragment {
3.1.onAttach
public void onAttach(Context context) {
super.onAttach(context);
mBackend = DreamBackend.getInstance(context);
//非充电状态下是否支持屏保
mDreamsSupportedOnBattery = getResources().getBoolean(
com.android.internal.R.bool.config_dreamsEnabledOnBattery);
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.when_to_dream_settings;
}
3.2.getCandidates
- mDreamsSupportedOnBattery 这个值影响选项的个数
protected List<? extends CandidateInfo> getCandidates() {
final String[] entries = entries();
final String[] values = keys();
final List<WhenToDreamCandidateInfo> candidates = new ArrayList<>();
if (entries == null || entries.length <= 0) return null;
if (values == null || values.length != entries.length) {
throw new IllegalArgumentException("Entries and values must be of the same length.");
}
for (int i = 0; i < entries.length; i++) {
candidates.add(new WhenToDreamCandidateInfo(entries[i], values[i]));
}
return candidates;
}
private String[] entries() {
if (mDreamsSupportedOnBattery) {
return getResources().getStringArray(R.array.when_to_start_screensaver_entries);
}
return getResources().getStringArray(R.array.when_to_start_screensaver_entries_no_battery);
}
private String[] keys() {
if (mDreamsSupportedOnBattery) {
return getResources().getStringArray(R.array.when_to_start_screensaver_values);
}
return getResources().getStringArray(R.array.when_to_start_screensaver_values_no_battery);
}
>keys
<string-array name="when_to_start_screensaver_values" translatable="false">
<item>while_charging_only</item>
<item>while_docked_only</item>
<item>either_charging_or_docked</item>
</string-array>
<!-- Values for screensaver "When to start" for devices that do not support screensavers
while on battery -->
<string-array name="when_to_start_screensaver_values_no_battery" translatable="false">
<item>while_charging_only</item>
<item>while_docked_only</item>
</string-array>
>entries
<string-array name="when_to_start_screensaver_entries" translatable="false">
<item>@string/screensaver_settings_summary_sleep</item>
<item>@string/screensaver_settings_summary_dock</item>
<item>@string/screensaver_settings_summary_either_long</item>
</string-array>
<!-- Options for screensaver "When to start" for devices that do not support screensavers
while on battery -->
<string-array name="when_to_start_screensaver_entries_no_battery" translatable="false">
<item>@string/screensaver_settings_summary_sleep</item>
<item>@string/screensaver_settings_summary_dock_and_charging</item>
</string-array>
<string name="screensaver_settings_summary_either_long" msgid="371949139331896271">"While charging or docked"</string>
<string name="screensaver_settings_summary_sleep" msgid="6555922932643037432">"While charging"</string>
<string name="screensaver_settings_summary_dock" msgid="6997766385189369733">"While docked"</string>
3.3.父类的实现类
//获取已保存的key值
protected String getDefaultKey() {
return DreamSettings.getKeyFromSetting(mBackend.getWhenToDreamSetting());
}
//保存选中的key值
protected boolean setDefaultKey(String key) {
mBackend.setWhenToDream(DreamSettings.getSettingFromPrefKey(key));
return true;
}
//选项点击以后的最终操作
protected void onSelectionPerformed(boolean success) {
super.onSelectionPerformed(success);
getActivity().finish();
}
3.4.RadioButtonPickerFragment.java
看下父类,简单看下单选功能如何实现的
>updateCandidates
根据数据动态添加列表选项
public void updateCandidates() {
mCandidates.clear();
final List<? extends CandidateInfo> candidateList = getCandidates();//数据获取子类实现
//..
final String defaultKey = getDefaultKey();
final String systemDefaultKey = getSystemDefaultKey();
final PreferenceScreen screen = getPreferenceScreen();
screen.removeAll();
//...
if (candidateList != null) {
for (CandidateInfo info : candidateList) {
//for循环动态创建preference
SelectorWithWidgetPreference pref =
new SelectorWithWidgetPreference(getPrefContext());
if (customLayoutResId > 0) {
pref.setLayoutResource(customLayoutResId);
}
//绑定数据
bindPreference(pref, info.getKey(), info, defaultKey);
//添加
screen.addPreference(pref);
}
}
//..
}
>bindPreference
public SelectorWithWidgetPreference bindPreference(SelectorWithWidgetPreference pref,
String key, CandidateInfo info, String defaultKey) {
pref.setTitle(info.loadLabel());
pref.setIcon(Utils.getSafeIcon(info.loadIcon()));
pref.setKey(key);
//pref的key跟默认的key比较,一样就是选中状态
if (TextUtils.equals(defaultKey, key)) {
pref.setChecked(true);
}
pref.setEnabled(info.enabled);
pref.setOnClickListener(this);
return pref;
}
>onRadioButtonClicked
public void onRadioButtonClicked(SelectorWithWidgetPreference selected) {
final String selectedKey = selected.getKey();
onRadioButtonConfirmed(selectedKey);
}
protected void onRadioButtonConfirmed(String selectedKey) {
//保存这个点击的选项的key
final boolean success = setDefaultKey(selectedKey);
if (success) {
//更新选中状态,这时候点击的key和保存的key一样,所以会设置为选中状态
updateCheckedState(selectedKey);
}
//点击以后的操作,子类实现,关闭页面
onSelectionPerformed(success);
}
4.DreamBackend.java
4.1.enable
可以看到,修改的是Settings的值
public boolean isEnabled() {
return getBoolean(Settings.Secure.SCREENSAVER_ENABLED, mDreamsEnabledByDefault);
}
public void setEnabled(boolean value) {
setBoolean(Settings.Secure.SCREENSAVER_ENABLED, value);
}
private boolean getBoolean(String key, boolean def) {
return Settings.Secure.getInt(mContext.getContentResolver(), key, def ? 1 : 0) == 1;
}
private void setBoolean(String key, boolean value) {
Settings.Secure.putInt(mContext.getContentResolver(), key, value ? 1 : 0);
}
4.2.when to drean
public int getWhenToDreamSetting() {
return isActivatedOnDock() && isActivatedOnSleep() ? EITHER
: isActivatedOnDock() ? WHILE_DOCKED
: isActivatedOnSleep() ? WHILE_CHARGING
: NEVER;
}
public void setWhenToDream(@WhenToDream int whenToDream) {
setEnabled(whenToDream != NEVER);
switch (whenToDream) {
case WHILE_CHARGING:
setActivatedOnDock(false);
setActivatedOnSleep(true);
break;
case WHILE_DOCKED:
setActivatedOnDock(true);
setActivatedOnSleep(false);
break;
case EITHER:
setActivatedOnDock(true);
setActivatedOnSleep(true);
break;
case NEVER:
default:
break;
}
}
4.3.getActiveDreamName
获取dream组件的名字
public CharSequence getActiveDreamName() {
ComponentName cn = getActiveDream();
if (cn != null) {
PackageManager pm = mContext.getPackageManager();
try {
ServiceInfo ri = pm.getServiceInfo(cn, 0);
if (ri != null) {
return ri.loadLabel(pm);
}
}
}
return null;
}
>getActiveDream
public ComponentName getActiveDream() {
if (mDreamManager == null) {
return null;
}
try {
ComponentName[] dreams = mDreamManager.getDreamComponents();
return dreams != null && dreams.length > 0 ? dreams[0] : null;
}
}
4.4.setActiveDream
public void setActiveDream(ComponentName dream) {
if (mDreamManager == null) {
return;
}
try {
ComponentName[] dreams = {dream};
mDreamManager.setDreamComponents(dream == null ? null : dreams);
}
}
4.5.getDreamInfos
- 可以看到,写个屏保很简单,service里的action是DreamService.SERVICE_INTERFACE就行了。
public List<DreamInfo> getDreamInfos() {
ComponentName activeDream = getActiveDream();
PackageManager pm = mContext.getPackageManager();
//查找对应action的service
Intent dreamIntent = new Intent(DreamService.SERVICE_INTERFACE);
List<ResolveInfo> resolveInfos = pm.queryIntentServices(dreamIntent,
PackageManager.GET_META_DATA);
List<DreamInfo> dreamInfos = new ArrayList<>(resolveInfos.size());
for (ResolveInfo resolveInfo : resolveInfos) {
final ComponentName componentName = getDreamComponentName(resolveInfo);
//mDisabledDreams数组是本地配置的,可以过滤自己不想要的
if (componentName == null || mDisabledDreams.contains(componentName)) {
continue;
}
DreamInfo dreamInfo = new DreamInfo();
dreamInfo.caption = resolveInfo.loadLabel(pm);
dreamInfo.icon = resolveInfo.loadIcon(pm);
dreamInfo.description = getDescription(resolveInfo, pm);
dreamInfo.componentName = componentName;
dreamInfo.isActive = dreamInfo.componentName.equals(activeDream);
final DreamService.DreamMetadata dreamMetadata = DreamService.getDreamMetadata(mContext,
resolveInfo.serviceInfo);
if (dreamMetadata != null) {
dreamInfo.settingsComponentName = dreamMetadata.settingsActivity;
dreamInfo.previewImage = dreamMetadata.previewImage;
}
dreamInfos.add(dreamInfo);
}
dreamInfos.sort(mComparator);
return dreamInfos;
}
4.6.setActivatedOnDock
public void setActivatedOnDock(boolean value) {
setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, value);
}
>setActivatedOnSleep
public void setActivatedOnSleep(boolean value) {
setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, value);
}
4.7. get|put boolean
private boolean getBoolean(String key, boolean def) {
return Settings.Secure.getInt(mContext.getContentResolver(), key, def ? 1 : 0) == 1;
}
private void setBoolean(String key, boolean value) {
Settings.Secure.putInt(mContext.getContentResolver(), key, value ? 1 : 0);
}
4.8. set|get ActiveDream
public void setActiveDream(ComponentName dream) {
if (mDreamManager == null) {
return;
}
try {
ComponentName[] dreams = {dream};
mDreamManager.setDreamComponents(dream == null ? null : dreams);
}
}
public ComponentName getActiveDream() {
if (mDreamManager == null) {
return null;
}
try {
ComponentName[] dreams = mDreamManager.getDreamComponents();
return dreams != null && dreams.length > 0 ? dreams[0] : null;
}
}
4.9.getWhenToDreamSetting
public int getWhenToDreamSetting() {
return isActivatedOnDock() && isActivatedOnSleep() ? EITHER
: isActivatedOnDock() ? WHILE_DOCKED
: isActivatedOnSleep() ? WHILE_CHARGING
: NEVER;
}
6.DarkModeActivationPreferenceController.java
以前的好像是点击弹个列表框选择,现在直接变成开关了,还可以配置dark模式的时间段,这里就简单研究下开关
6.1.onSwitchChanged
黑夜模式交给manager来处理了
public void onSwitchChanged(Switch switchView, boolean isChecked) {
mMetricsFeatureProvider.logClickedPreference(mPreference, getMetricsCategory());
final boolean active = (mContext.getResources().getConfiguration().uiMode
& Configuration.UI_MODE_NIGHT_YES) != 0;
mUiModeManager.setNightModeActivated(!active);
}
>setNightModeActivated
UiModeManager.java
@RequiresPermission(android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
public boolean setNightModeActivated(boolean active) {
if (mService != null) {
try {
//跨进程操作,最终实现是 小节7.1
return mService.setNightModeActivated(active);
}
}
return false;
}
7.UiModeManagerService.java
7.1.setNightModeActivated
修改mNightMode的方法一
private final IUiModeManager.Stub mService = new IUiModeManager.Stub() {
public boolean setNightModeActivated(boolean active) {
return setNightModeActivatedForModeInternal(mNightModeCustomType, active);
}
private boolean setNightModeActivatedForModeInternal(int modeCustomType, boolean active) {
if (getContext().checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
final int user = Binder.getCallingUserHandle().getIdentifier();
if (user != mCurrentUser && getContext().checkCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
if (modeCustomType == MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
mLastBedtimeRequestedNightMode = active;
}
if (modeCustomType != mNightModeCustomType) {
return false;
}
synchronized (mLock) {
final long ident = Binder.clearCallingIdentity();
try {
if (mNightMode == MODE_NIGHT_AUTO || mNightMode == MODE_NIGHT_CUSTOM) {
unregisterScreenOffEventLocked();
mOverrideNightModeOff = !active;
mOverrideNightModeOn = active;
mOverrideNightModeUser = mCurrentUser;
persistNightModeOverrides(mCurrentUser);
} else if (mNightMode == UiModeManager.MODE_NIGHT_NO
&& active) {
//默认是no,所以设置里开关应该是关闭的,打开以后会走这里,改为yes
mNightMode = UiModeManager.MODE_NIGHT_YES;
} else if (mNightMode == UiModeManager.MODE_NIGHT_YES
&& !active) {
//再次关闭又走这里
mNightMode = UiModeManager.MODE_NIGHT_NO;
}
updateConfigurationLocked();
applyConfigurationExternallyLocked();
persistNightMode(mCurrentUser);
return true;
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
7.2.setNightMode
修改mNightMode的方法二
public void setNightMode(int mode) {
int customModeType = mode == MODE_NIGHT_CUSTOM
? MODE_NIGHT_CUSTOM_TYPE_SCHEDULE
: MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
setNightModeInternal(mode, customModeType);
}
private void setNightModeInternal(int mode, int customModeType) {
if (isNightModeLocked() && (getContext().checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
!= PackageManager.PERMISSION_GRANTED)) {
return;
}
switch (mode) {
case UiModeManager.MODE_NIGHT_NO:
case UiModeManager.MODE_NIGHT_YES:
case MODE_NIGHT_AUTO:
break;
case MODE_NIGHT_CUSTOM:
if (SUPPORTED_NIGHT_MODE_CUSTOM_TYPES.contains(customModeType)) {
break;
}
throw new IllegalArgumentException(
"Can't set the custom type to " + customModeType);
default:
throw new IllegalArgumentException("Unknown mode: " + mode);
}
final int user = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
if (mNightMode != mode || mNightModeCustomType != customModeType) {
if (mNightMode == MODE_NIGHT_AUTO || mNightMode == MODE_NIGHT_CUSTOM) {
unregisterScreenOffEventLocked();
cancelCustomAlarm();
}
mNightModeCustomType = mode == MODE_NIGHT_CUSTOM
? customModeType
: MODE_NIGHT_CUSTOM_TYPE_UNKNOWN;
//设置为新的mode
mNightMode = mode;
resetNightModeOverrideLocked();
persistNightMode(user);
// on screen off will update configuration instead
if ((mNightMode != MODE_NIGHT_AUTO && mNightMode != MODE_NIGHT_CUSTOM)
|| shouldApplyAutomaticChangesImmediately()) {
unregisterScreenOffEventLocked();
updateLocked(0, 0);
} else {
registerScreenOffEventLocked();
}
}
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
7.3.onStart
- 看下mNightMode的默认值,配置里是1,也就是MODE_NIGHT_NO
- 先直接读取资源文件里的默认配置,完事在开启线程读取settings里存储的值
public void onStart() {
final Context context = getContext();
verifySetupWizardCompleted();
final Resources res = context.getResources();
mStartDreamImmediatelyOnDock = res.getBoolean(
com.android.internal.R.bool.config_startDreamImmediatelyOnDock);
mDreamsDisabledByAmbientModeSuppression = res.getBoolean(
com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig);
//默认值是1
mNightMode = res.getInteger(
com.android.internal.R.integer.config_defaultNightMode);
mDefaultUiModeType = res.getInteger(
com.android.internal.R.integer.config_defaultUiModeType);
mCarModeKeepsScreenOn = (res.getInteger(
com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1);
mDeskModeKeepsScreenOn = (res.getInteger(
com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
mEnableCarDockLaunch = res.getBoolean(
com.android.internal.R.bool.config_enableCarDockHomeLaunch);
mUiModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockUiMode);
mNightModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockDayNightMode);
final PackageManager pm = context.getPackageManager();
mTelevision = pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
|| pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
mCar = pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
mWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
// Update the initial, static configurations.
SystemServerInitThreadPool.submit(() -> {
synchronized (mLock) {
TwilightManager twilightManager = getLocalService(TwilightManager.class);
if (twilightManager != null) mTwilightManager = twilightManager;
//重新拉去settings的值
updateNightModeFromSettingsLocked(context, res, UserHandle.getCallingUserId());
updateSystemProperties();
}
}, TAG + ".onStart");
publishBinderService(Context.UI_MODE_SERVICE, mService);
publishLocalService(UiModeManagerInternal.class, mLocalService);
}
>config_defaultNightMode
<!-- Control the default night mode to use when there is no other mode override set.
One of the following values (see UiModeManager.java):
0 - MODE_NIGHT_AUTO
1 - MODE_NIGHT_NO
2 - MODE_NIGHT_YES
-->
<integer name="config_defaultNightMode">1</integer>
7.3.updateNightModeFromSettingsLocked
private void updateNightModeFromSettingsLocked(Context context, Resources res, int userId) {
if (mCarModeEnabled || mCar) {
return;
}
if (mSetupWizardComplete) {
//获取Settings里存储的值
mNightMode = Secure.getIntForUser(context.getContentResolver(),
Secure.UI_NIGHT_MODE, res.getInteger(
com.android.internal.R.integer.config_defaultNightMode), userId);
8.总结
- 简单研究下设置里的屏保功能,包括总开关,屏保程序的选择,屏保触发的条件
- 简单看了下dark mode选项开关的操作,最终保存的啥数据。