Loading core/java/com/android/internal/config/appcloning/AppCloningDeviceConfigHelper.java 0 → 100644 +107 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source 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 com.android.internal.config.appcloning; import android.content.Context; import android.provider.DeviceConfig; import com.android.internal.annotations.GuardedBy; /** * Helper class that holds the flags related to the app_cloning namespace in {@link DeviceConfig}. * * @hide */ public class AppCloningDeviceConfigHelper { @GuardedBy("sLock") private static AppCloningDeviceConfigHelper sInstance; private static final Object sLock = new Object(); private DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangeListener; /** * This flag is defined inside {@link DeviceConfig#NAMESPACE_APP_CLONING}. Please check * {@link #mEnableAppCloningBuildingBlocks} for details. */ public static final String ENABLE_APP_CLONING_BUILDING_BLOCKS = "enable_app_cloning_building_blocks"; /** * Checks whether the support for app-cloning building blocks (like contacts * sharing/intent redirection), which are available starting from the U release, is turned on. * The default value is true to ensure the features are always enabled going forward. * * TODO:(b/253449368) Add information about the app-cloning config and mention that the devices * that do not support app-cloning should use the app-cloning config to disable all app-cloning * features. */ private volatile boolean mEnableAppCloningBuildingBlocks = true; private AppCloningDeviceConfigHelper() {} /** * @hide */ public static AppCloningDeviceConfigHelper getInstance(Context context) { synchronized (sLock) { if (sInstance == null) { sInstance = new AppCloningDeviceConfigHelper(); sInstance.init(context); } return sInstance; } } private void init(Context context) { initializeDeviceConfigChangeListener(); DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_APP_CLONING, context.getMainExecutor(), mDeviceConfigChangeListener); } private void initializeDeviceConfigChangeListener() { mDeviceConfigChangeListener = properties -> { if (!DeviceConfig.NAMESPACE_APP_CLONING.equals(properties.getNamespace())) { return; } for (String name : properties.getKeyset()) { if (name == null) { return; } if (ENABLE_APP_CLONING_BUILDING_BLOCKS.equals(name)) { updateEnableAppCloningBuildingBlocks(); } } }; } private void updateEnableAppCloningBuildingBlocks() { mEnableAppCloningBuildingBlocks = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_APP_CLONING, ENABLE_APP_CLONING_BUILDING_BLOCKS, true); } /** * Fetch the feature flag to check whether the support for the app-cloning building blocks * (like contacts sharing/intent redirection) is enabled on the device. * @hide */ public boolean getEnableAppCloningBuildingBlocks() { return mEnableAppCloningBuildingBlocks; } } core/java/com/android/internal/config/appcloning/OWNERS 0 → 100644 +3 −0 Original line number Diff line number Diff line # Bug component: 1207885 jigarthakkar@google.com saumyap@google.com No newline at end of file services/core/java/com/android/server/content/SyncManager.java +19 −1 Original line number Diff line number Diff line Loading @@ -104,6 +104,7 @@ import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.internal.config.appcloning.AppCloningDeviceConfigHelper; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.os.BackgroundThread; Loading Loading @@ -264,6 +265,8 @@ public class SyncManager { private final SyncLogger mLogger; private final AppCloningDeviceConfigHelper mAppCloningDeviceConfigHelper; private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) { for (int i = 0, size = pendingJobs.size(); i < size; i++) { JobInfo job = pendingJobs.get(i); Loading Loading @@ -627,6 +630,7 @@ public class SyncManager { }, mSyncHandler); mConstants = new SyncManagerConstants(context); mAppCloningDeviceConfigHelper = AppCloningDeviceConfigHelper.getInstance(context); IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); context.registerReceiver(mConnectivityIntentReceiver, intentFilter); Loading Loading @@ -827,6 +831,18 @@ public class SyncManager { } } /** * Check whether the feature flag controlling contacts sharing for clone profile is set. If * true, the contact syncs for clone profile should be disabled. * * @return true/false if contact sharing is enabled/disabled */ protected boolean isContactSharingAllowedForCloneProfile() { // TODO(b/253449368): This method should also check for the config controlling // all app-cloning features. return mAppCloningDeviceConfigHelper.getEnableAppCloningBuildingBlocks(); } /** * Check if account sync should be disabled for the given user and provider. * @param userInfo Loading @@ -836,7 +852,9 @@ public class SyncManager { */ @VisibleForTesting protected boolean shouldDisableSyncForUser(UserInfo userInfo, String providerName) { if (userInfo == null || providerName == null) return false; if (userInfo == null || providerName == null || !isContactSharingAllowedForCloneProfile()) { return false; } return providerName.equals(ContactsContract.AUTHORITY) && !areContactWritesEnabledForUser(userInfo); } Loading services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; Loading Loading @@ -95,7 +96,7 @@ public class SyncManagerTest extends TestCase { when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); doNothing().when(mAccountManagerInternal).addOnAppPermissionChangeListener(any()); when(mJobSchedulerInternal.getSystemScheduledPendingJobs()).thenReturn(new ArrayList<>()); mSyncManager = new SyncManagerWithMockedServices(mContext, true); mSyncManager = spy(new SyncManagerWithMockedServices(mContext, true)); } public void testSyncExtrasEquals_WithNull() throws Exception { Loading Loading @@ -233,6 +234,7 @@ public class SyncManagerTest extends TestCase { } public void testShouldDisableSync() { doReturn(true).when(mSyncManager).isContactSharingAllowedForCloneProfile(); UserInfo primaryUserInfo = createUserInfo("primary", 0 /* id */, 0 /* groupId */, UserInfo.FLAG_PRIMARY | UserInfo.FLAG_ADMIN); UserInfo cloneUserInfo = createUserInfo("clone", 10 /* id */, 0 /* groupId */, Loading Loading
core/java/com/android/internal/config/appcloning/AppCloningDeviceConfigHelper.java 0 → 100644 +107 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source 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 com.android.internal.config.appcloning; import android.content.Context; import android.provider.DeviceConfig; import com.android.internal.annotations.GuardedBy; /** * Helper class that holds the flags related to the app_cloning namespace in {@link DeviceConfig}. * * @hide */ public class AppCloningDeviceConfigHelper { @GuardedBy("sLock") private static AppCloningDeviceConfigHelper sInstance; private static final Object sLock = new Object(); private DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangeListener; /** * This flag is defined inside {@link DeviceConfig#NAMESPACE_APP_CLONING}. Please check * {@link #mEnableAppCloningBuildingBlocks} for details. */ public static final String ENABLE_APP_CLONING_BUILDING_BLOCKS = "enable_app_cloning_building_blocks"; /** * Checks whether the support for app-cloning building blocks (like contacts * sharing/intent redirection), which are available starting from the U release, is turned on. * The default value is true to ensure the features are always enabled going forward. * * TODO:(b/253449368) Add information about the app-cloning config and mention that the devices * that do not support app-cloning should use the app-cloning config to disable all app-cloning * features. */ private volatile boolean mEnableAppCloningBuildingBlocks = true; private AppCloningDeviceConfigHelper() {} /** * @hide */ public static AppCloningDeviceConfigHelper getInstance(Context context) { synchronized (sLock) { if (sInstance == null) { sInstance = new AppCloningDeviceConfigHelper(); sInstance.init(context); } return sInstance; } } private void init(Context context) { initializeDeviceConfigChangeListener(); DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_APP_CLONING, context.getMainExecutor(), mDeviceConfigChangeListener); } private void initializeDeviceConfigChangeListener() { mDeviceConfigChangeListener = properties -> { if (!DeviceConfig.NAMESPACE_APP_CLONING.equals(properties.getNamespace())) { return; } for (String name : properties.getKeyset()) { if (name == null) { return; } if (ENABLE_APP_CLONING_BUILDING_BLOCKS.equals(name)) { updateEnableAppCloningBuildingBlocks(); } } }; } private void updateEnableAppCloningBuildingBlocks() { mEnableAppCloningBuildingBlocks = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_APP_CLONING, ENABLE_APP_CLONING_BUILDING_BLOCKS, true); } /** * Fetch the feature flag to check whether the support for the app-cloning building blocks * (like contacts sharing/intent redirection) is enabled on the device. * @hide */ public boolean getEnableAppCloningBuildingBlocks() { return mEnableAppCloningBuildingBlocks; } }
core/java/com/android/internal/config/appcloning/OWNERS 0 → 100644 +3 −0 Original line number Diff line number Diff line # Bug component: 1207885 jigarthakkar@google.com saumyap@google.com No newline at end of file
services/core/java/com/android/server/content/SyncManager.java +19 −1 Original line number Diff line number Diff line Loading @@ -104,6 +104,7 @@ import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.internal.config.appcloning.AppCloningDeviceConfigHelper; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.os.BackgroundThread; Loading Loading @@ -264,6 +265,8 @@ public class SyncManager { private final SyncLogger mLogger; private final AppCloningDeviceConfigHelper mAppCloningDeviceConfigHelper; private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) { for (int i = 0, size = pendingJobs.size(); i < size; i++) { JobInfo job = pendingJobs.get(i); Loading Loading @@ -627,6 +630,7 @@ public class SyncManager { }, mSyncHandler); mConstants = new SyncManagerConstants(context); mAppCloningDeviceConfigHelper = AppCloningDeviceConfigHelper.getInstance(context); IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); context.registerReceiver(mConnectivityIntentReceiver, intentFilter); Loading Loading @@ -827,6 +831,18 @@ public class SyncManager { } } /** * Check whether the feature flag controlling contacts sharing for clone profile is set. If * true, the contact syncs for clone profile should be disabled. * * @return true/false if contact sharing is enabled/disabled */ protected boolean isContactSharingAllowedForCloneProfile() { // TODO(b/253449368): This method should also check for the config controlling // all app-cloning features. return mAppCloningDeviceConfigHelper.getEnableAppCloningBuildingBlocks(); } /** * Check if account sync should be disabled for the given user and provider. * @param userInfo Loading @@ -836,7 +852,9 @@ public class SyncManager { */ @VisibleForTesting protected boolean shouldDisableSyncForUser(UserInfo userInfo, String providerName) { if (userInfo == null || providerName == null) return false; if (userInfo == null || providerName == null || !isContactSharingAllowedForCloneProfile()) { return false; } return providerName.equals(ContactsContract.AUTHORITY) && !areContactWritesEnabledForUser(userInfo); } Loading
services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; Loading Loading @@ -95,7 +96,7 @@ public class SyncManagerTest extends TestCase { when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); doNothing().when(mAccountManagerInternal).addOnAppPermissionChangeListener(any()); when(mJobSchedulerInternal.getSystemScheduledPendingJobs()).thenReturn(new ArrayList<>()); mSyncManager = new SyncManagerWithMockedServices(mContext, true); mSyncManager = spy(new SyncManagerWithMockedServices(mContext, true)); } public void testSyncExtrasEquals_WithNull() throws Exception { Loading Loading @@ -233,6 +234,7 @@ public class SyncManagerTest extends TestCase { } public void testShouldDisableSync() { doReturn(true).when(mSyncManager).isContactSharingAllowedForCloneProfile(); UserInfo primaryUserInfo = createUserInfo("primary", 0 /* id */, 0 /* groupId */, UserInfo.FLAG_PRIMARY | UserInfo.FLAG_ADMIN); UserInfo cloneUserInfo = createUserInfo("clone", 10 /* id */, 0 /* groupId */, Loading