Android 13 about launcher3 (1)

Android 13 Launcher3
android13#launcher3#分屏相关

Launcher3修改 wm density界面布局不改变
复制代码
/packages/apps/Launcher3/src/com/android/launcher3/InvariantDeviceProfile.java
Launcher的默认配置加载类,通过InvariantDeviceProfile方法可以看出,
CellLayout显示的应用行数和列数可以通过findClosestDeviceProfiles查询XML配置来读取配参

Launcher3图标布局原理解析

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设置默认桌面

相关推荐
whysqwhw1 小时前
安卓图片性能优化技巧
android
风往哪边走1 小时前
自定义底部筛选弹框
android
Yyyy4822 小时前
MyCAT基础概念
android
Android轮子哥2 小时前
尝试解决 Android 适配最后一公里
android
雨白3 小时前
OkHttp 源码解析:enqueue 非同步流程与 Dispatcher 调度
android
风往哪边走4 小时前
自定义仿日历组件弹框
android
没有了遇见4 小时前
Android 外接 U 盘开发实战:从权限到文件复制
android
Monkey-旭5 小时前
Android 文件存储机制全解析
android·文件存储·kolin
zhangphil6 小时前
Android Coil 3拦截器Interceptor计算单次请求耗时,Kotlin
android·kotlin
DokiDoki之父6 小时前
多线程—飞机大战排行榜功能(2.0版本)
android·java·开发语言