Android 13 Launcher3
android13#launcher3#分屏相关
Launcher3修改 wm density界面布局不改变
/packages/apps/Launcher3/src/com/android/launcher3/InvariantDeviceProfile.java
Launcher的默认配置加载类,通过InvariantDeviceProfile方法可以看出,
CellLayout显示的应用行数和列数可以通过findClosestDeviceProfiles查询XML配置来读取配参
Android 13 diff
index 02ebb15cd1..36ce9bf7bf 100644
--- a/packages/apps/Launcher3/src/com/android/launcher3/util/DisplayController.java
+++ b/packages/apps/Launcher3/src/com/android/launcher3/util/DisplayController.java
@@ -284,7 +284,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
if (change != 0) {
mInfo = newInfo;
final int flags = change;
- MAIN_EXECUTOR.execute(() -> notifyChange(displayInfoContext, flags));
+ //MAIN_EXECUTOR.execute(() -> notifyChange(displayInfoContext, flags));
}
}
Android 11 diff
./packages/apps/Launcher3/src/com/android/launcher3/util/ConfigMonitor.java
@Override
public void onDisplayChanged(int displayId) {
if (displayId != mDisplayId) {
return;
}
Display display = getDefaultDisplay(mContext);
display.getRealSize(mTmpPoint1);
if (!mRealSize.equals(mTmpPoint1) && !mRealSize.equals(mTmpPoint1.y, mTmpPoint1.x)) {
LogUtils.d(TAG, String.format("Display size changed from %s to %s", mRealSize, mTmpPoint1));
notifyChange();
return;
}
display.getCurrentSizeRange(mTmpPoint1, mTmpPoint2);
if (!mSmallestSize.equals(mTmpPoint1) || !mLargestSize.equals(mTmpPoint2)) {
LogUtils.d(TAG, String.format("Available size changed from [%s, %s] to [%s, %s]",
mSmallestSize, mLargestSize, mTmpPoint1, mTmpPoint2));
notifyChange();
}
}
public synchronized void notifyChange() {
if (mCallback != null) {
Consumer<Context> callback = mCallback;
mCallback = null;
new MainThreadExecutor().execute(() -> {
//add text
//LauncherAppMonitor.getInstance(mContext).onUIConfigChanged();
//callback.accept(mContext);
//add text
});
}
}
Android 13 关于旋转屏幕之后,按home键回Launcher3失效
//自动旋转
public static final String ACCELEROMETER_ROTATION = "accelerometer_rotation";
adb shell settings get system accelerometer_rotation --> 0 off 1 on
Android 12之后,Launcher3有两个模式,一个是平板,另一个是手机.
手机模式:桌面默认是不可以旋转的.
桌面设置页面:桌面空白处长按,进入home settings,有个allow home screen rotation就是旋转开关,手机模式默认是关闭的,平板模式这个偏好隐藏了.
./packages/apps/Launcher3/res/values/config.xml
<string name="settings_fragment_name" translatable="false">com.android.launcher3.settings.SettingsActivity$LauncherSettingsFragment</string>
./packages/apps/Launcher3/src/com/android/launcher3/settings/SettingsActivity.java
public static class LauncherSettingsFragment extends PreferenceFragmentCompat
{
protected boolean initPreference(Preference preference) {
switch (preference.getKey()) {
case NOTIFICATION_DOTS_PREFERENCE_KEY:
return !WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS;
case ALLOW_ROTATION_PREFERENCE_KEY:
DisplayController.Info info =
DisplayController.INSTANCE.get(getContext()).getInfo();
if (info.isTablet(info.realBounds)) {
// Launcher supports rotation by default. No need to show this setting.
//是平板,不显示这个选项
return false;
}
// Initialize the UI once //非平板,默认显示,
preference.setDefaultValue(RotationHelper.getAllowRotationDefaultValue(info));//控制是否旋转
return true;
...
}
}
./packages/apps/Launcher3/src/com/android/launcher3/states/RotationHelper.java
public static boolean getAllowRotationDefaultValue(DisplayController.Info info) {
android.util.Log.d("tag","info.currentSize.x: " +info.currentSize.x);
android.util.Log.d("tag","info.currentSize.y: " +info.currentSize.y);
float originalSmallestWidth = dpiFromPx(Math.min(info.currentSize.x, info.currentSize.y),
DENSITY_DEVICE_STABLE);
return originalSmallestWidth >= MIN_TABLET_WIDTH;//MIN_TABLET_WIDTH = 600;
}
public static float dpiFromPx(float size, int densityDpi) {
float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT;//DENSITY_DEFAULT=160;
return (size / densityRatio);
}
//关于DENSITY_DEVICE_STABLE
private static int getDeviceDensity() {
//ro.sf.lcd_density的值在初始化进程的时候从build.prop里读取写入一次,之后不会修改
//qemu.sf.lcd_density覆写上边的值,目的是在模拟器的时候可以动态修改
return SystemProperties.getInt("qemu.sf.lcd_density",
SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
}
initialize()->初始化setIgnoreAutoRotateSettings
private void setIgnoreAutoRotateSettings(boolean ignoreAutoRotateSettings,
DisplayController.Info info) {
// On large devices we do not handle auto-rotate differently.
mIgnoreAutoRotateSettings = ignoreAutoRotateSettings;
if (!mIgnoreAutoRotateSettings) {
mHomeRotationEnabled = LauncherPrefs.get(mActivity).get(ALLOW_ROTATION);
LauncherPrefs.get(mActivity).addListener(this, ALLOW_ROTATION);
} else {
LauncherPrefs.get(mActivity).removeListener(this, ALLOW_ROTATION);
}
}
//手动控制屏幕旋转的方式
private void setOritation(int i) {
try {
IWindowManager windowManagerService = WindowManagerGlobal.getWindowManagerService();
if (i == 0) {
windowManagerService.freezeRotation(0);
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 0);//关闭自动旋转
} else if (i == 90) {
windowManagerService.freezeRotation(1);
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 0);
} else if (i == 180) {
windowManagerService.freezeRotation(2);
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 0);
} else if (i == 270) {
windowManagerService.freezeRotation(3);
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 0);
} else if (i == -1) {
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 1);//打开自动旋转
}
} catch (Exception e) {
...
}
}
Settings.System.getInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, 0);
adb shell settings get system user_rotation(修改后查询)
//修改 默认打开主界面旋转
+++ b/packages/apps/Launcher3/res/xml/launcher_preferences.xml
@@ -45,7 +45,7 @@
android:key="pref_allowRotation"
android:title="@string/allow_rotation_title"
android:summary="@string/allow_rotation_desc"
- android:defaultValue="false"
+ android:defaultValue="true"
android:persistent="true"
launcher:logIdOn="615"
launcher:logIdOff="616" />
diff --git a/packages/apps/Launcher3/src/com/android/launcher3/states/RotationHelper.java b/packages/apps/Launcher3/src/com/android/launcher3/states/RotationHelper.java
index 7b4e2485ce..6693f9f123 100644
--- a/packages/apps/Launcher3/src/com/android/launcher3/states/RotationHelper.java
+++ b/packages/apps/Launcher3/src/com/android/launcher3/states/RotationHelper.java
@@ -55,7 +55,7 @@ public class RotationHelper implements OnSharedPreferenceChangeListener,
// original dimensions to determine if rotation is allowed of not.
float originalSmallestWidth = dpiFromPx(Math.min(info.currentSize.x, info.currentSize.y),
DENSITY_DEVICE_STABLE);
- return originalSmallestWidth >= MIN_TABLET_WIDTH;
+ return true;//originalSmallestWidth >= MIN_TABLET_WIDTH;//add text
}
从源头隐藏某个apk不在最近应用(RecentView)显示
//这个改法:再需要隐藏的app,按Recent,有动画时显得卡顿,建议可以在Launcher3内尝试隐藏
frameworks/base/services/core/java/com/android/server/wm/RecentTasks.java
/**
* @return the list of recent tasks for presentation.
*/
private ArrayList<ActivityManager.RecentTaskInfo> getRecentTasksImpl(int maxNum, int flags,
boolean getTasksAllowed, int userId, int callingUid) {
final boolean withExcluded = (flags & RECENT_WITH_EXCLUDED) != 0;
if (!isUserRunning(userId, FLAG_AND_UNLOCKED)) {
Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents");
return new ArrayList<>();
}
loadUserRecentsLocked(userId);
final Set<Integer> includedUsers = getProfileIds(userId);
includedUsers.add(Integer.valueOf(userId));
final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
final int size = mTasks.size();
int numVisibleTasks = 0;
for (int i = 0; i < size; i++) {
final Task task = mTasks.get(i);
if (isVisibleRecentTask(task)) {
numVisibleTasks++;
if (isInVisibleRange(task, i, numVisibleTasks, withExcluded)) {
// Fall through
} else {
// Not in visible range
continue;
}
} else {
// Not visible
continue;
}
// Skip remaining tasks once we reach the requested size
if (res.size() >= maxNum) {
continue;
}
// Only add calling user or related users recent tasks
if (!includedUsers.contains(Integer.valueOf(task.mUserId))) {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + task);
continue;
}
...
//add text
ComponentName cn = task.intent.getComponent();
if(cn != null && cn.getPackageName().equals("com.xxx.xxx")){
continue;
}else{
res.add(createRecentTaskInfo(task, true /* stripExtras */));
}
//add text
}
return res;
}
Android T Launcher3
Android T Launcher3_recentView
T replace default launcher
关于3.0Ver 利用role不需要删除旧Launcher栈的补充.
case 1: 单独使用role,确实不需要删除旧Launcher栈,唯一需要注意点的是要在Launcher启动之前,把android.app.role.HOME
替换,
所以需要在framework里某个必经之路上做文章..
//about home role
packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/role/model/HomeRoleBehavior.java
packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/role/ui/ManageRoleHolderStateLiveData.java
packages/modules/Permission/service/java/com/android/role/RoleService.java
addRoleHolderAsUser(...)
removeRoleHolderAsUser(...)
getRoleHoldersAsUser(...)
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
+import android.app.role.RoleManager;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
@Override
public void systemReady() {
// In normal flow, systemReady is called before other system services are ready.
// So it is better not to bind keyguard here.
mKeyguardDelegate.onSystemReady();
...
mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
mGestureLauncherService = LocalServices.getService(GestureLauncherService.class);
+ setDefaultLauncherItemToHomeRole(mContext);//add
}
public void setDefaultLauncherItemToHomeRole(Context context) {
RoleManager roleManager = context.getSystemService(RoleManager.class);
String packageName = SystemProperties.get("persist.xx.def_xxx_launcher", null);
List<String> list = roleManager_1.getRoleHolders("android.app.role.HOME");
boolean repeat_flag = false;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals(packageName)) {
flag = true;
}
}
if (repeat_flag) return;
if (packageName != null && !"".equals(packageName)) {
String roleName = "android.app.role.HOME";
boolean add = true;
int flags = 0;
UserHandle user = Process.myUserHandle();
Log.d("tag", "role: " + roleName + ", package: " + packageName);
Executor executor = context.getMainExecutor();
Consumer<Boolean> callback = successful -> {
if (successful) {
Log.d("tag", "Success , role: " + roleName + ", package: " + packageName);
} else {
Log.d("tag", "Failed , role: " + roleName + ", package: " + packageName);
}
};
roleManager.addRoleHolderAsUser(roleName, packageName, flags, user, executor, callback);
}
}
case 2:ResolverActivity
frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
onCreate()->rebuildList()->onPostListReady()->isAutolaunching()...
protected void onCreate(Bundle savedInstanceState, Intent intent,
CharSequence title, int defaultTitleRes, Intent[] initialIntents,
List<ResolveInfo> rList, boolean supportsAlwaysUseOption) {
setTheme(appliedThemeResId());
super.onCreate(savedInstanceState);
//add text
if(true){
setDefaultLauncher("com.xx.xxx");
finish();
return;
}
//add text
mQuietModeManager = createQuietModeManager();
...
}
//add text
private List<ResolveInfo> getResolveInfoList() {
PackageManager pm = getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_HOME);
intent.addCategory(Intent.CATEGORY_DEFAULT);
return pm.queryIntentActivities(intent, 0);
}
private ResolveInfo getCurrentLauncher() {
PackageManager pm = getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_HOME);
intent.addCategory(Intent.CATEGORY_DEFAULT);
return pm.resolveActivity(intent, 0);
}
private void setDefaultLauncher(String packageName) {
PackageManager pm = getPackageManager();
ResolveInfo oldCurrentLauncher = getCurrentLauncher();
List<ResolveInfo> packageInfos = getResolveInfoList();
ResolveInfo customerLauncher = null;
for (ResolveInfo ri : packageInfos) {
if (!TextUtils.isEmpty(ri.activityInfo.packageName) && !TextUtils.isEmpty(packageName)
&& TextUtils.equals(ri.activityInfo.packageName, packageName)) {
customerLauncher = ri;
}
}
if (customerLauncher == null) return;
pm.clearPackagePreferredActivities(oldCurrentLauncher.activityInfo.packageName);//clear old Launcher
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MAIN);
intentFilter.addCategory(Intent.CATEGORY_HOME);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
ComponentName componentName = new ComponentName(customerLauncher.activityInfo.packageName,
customerLauncher.activityInfo.name);
ComponentName[] componentNames = new ComponentName[packageInfos.size()];
int defaultMatch = 0;
for (int i = 0; i < packageInfos.size(); i++) {
ResolveInfo resolveInfo = packageInfos.get(i);
componentNames[i] = new ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
if (defaultMatch < resolveInfo.match) {
defaultMatch = resolveInfo.match;
}
}
pm.clearPackagePreferredActivities(oldCurrentLauncher.activityInfo.packageName);
pm.addPreferredActivity(intentFilter, defaultMatch, componentNames, componentName);
}
//add text
Android13设置默认Launcher分析
Android13设置默认Launcher分析
RK3588 Android13 预安装自己的apk应用及把这个应用设置为默认桌面
Android R设置默认桌面