[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: 85ef2dc7b1 -s ours
am skip reason: subject contains skip directive
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/DocumentsUI/+/18985519
Change-Id: I2da961e862afca9e1bc4c8017ab8bf87d15ccf32
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/Android.bp b/Android.bp
index 88ebeba..f8c3e20 100644
--- a/Android.bp
+++ b/Android.bp
@@ -54,6 +54,7 @@
"apache-commons-compress",
"com.google.android.material_material",
"guava",
+ "modules-utils-build_system",
],
libs: [
@@ -136,6 +137,7 @@
static_libs: [
"androidx.appcompat_appcompat",
"com.google.android.material_material",
+ "modules-utils-build_system",
],
resource_dirs: [
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8b86feb..e15805e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -31,6 +31,7 @@
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.MODIFY_QUIET_MODE" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Permissions required for reading and logging compat changes -->
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
diff --git a/OWNERS b/OWNERS
index 72407f3..cc1508c 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,3 @@
-# Default code reviewers picked from top 3 or more developers.
-# Please update this list if you find better candidates.
[email protected]
[email protected]
+# Bug component: 46626
+
+include platform/frameworks/base:/core/java/android/os/storage/OWNERS
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 742f12e..c12abc8 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,4 +1,13 @@
{
+ "presubmit": [
+ {
+ "name": "DocumentsUIGoogleTests",
+ "keywords": ["primary-device"]
+ },
+ {
+ "name": "DocumentsUIUnitTests"
+ }
+ ],
"postsubmit": [
{
"name": "DocumentsUIGoogleTests",
diff --git a/res/layout-sw720dp/item_doc_list.xml b/res/layout-sw720dp/item_doc_list.xml
index cf74909..da91796 100644
--- a/res/layout-sw720dp/item_doc_list.xml
+++ b/res/layout-sw720dp/item_doc_list.xml
@@ -110,7 +110,7 @@
android:ellipsize="middle"
android:singleLine="true"
android:textAlignment="viewStart"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
+ android:textAppearance="@style/Subhead"
android:textColor="?android:attr/textColorPrimary"/>
</LinearLayout>
@@ -123,7 +123,7 @@
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
+ android:textAppearance="@style/Body1"
android:textColor="?android:attr/textColorSecondary" />
<TextView
@@ -136,7 +136,7 @@
android:minWidth="70dp"
android:singleLine="true"
android:textAlignment="viewEnd"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
+ android:textAppearance="@style/Body1"
android:textColor="?android:attr/textColorSecondary" />
<TextView
@@ -149,7 +149,7 @@
android:minWidth="70dp"
android:singleLine="true"
android:textAlignment="viewEnd"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
+ android:textAppearance="@style/Body1"
android:textColor="?android:attr/textColorSecondary" />
</LinearLayout>
diff --git a/res/layout-sw720dp/shared_cell_content.xml b/res/layout-sw720dp/shared_cell_content.xml
index dc37f2c..9346933 100644
--- a/res/layout-sw720dp/shared_cell_content.xml
+++ b/res/layout-sw720dp/shared_cell_content.xml
@@ -23,7 +23,7 @@
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
- android:textAppearance="@*style/android:TextAppearance.DeviceDefault.Subhead"
+ android:textAppearance="@style/Subhead"
android:textColor="?android:attr/textColorSecondary"/>
<ImageView
diff --git a/res/layout/dialog_delete_confirmation.xml b/res/layout/dialog_delete_confirmation.xml
index d5b133e..80879ad 100644
--- a/res/layout/dialog_delete_confirmation.xml
+++ b/res/layout/dialog_delete_confirmation.xml
@@ -21,5 +21,5 @@
android:paddingTop="24dp"
android:paddingStart="24dp"
android:paddingEnd="24dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead">
+ android:textAppearance="@style/Subhead">
</TextView>
diff --git a/res/layout/drag_shadow_layout.xml b/res/layout/drag_shadow_layout.xml
index 75bd0ca..591e813 100644
--- a/res/layout/drag_shadow_layout.xml
+++ b/res/layout/drag_shadow_layout.xml
@@ -40,7 +40,7 @@
android:maxLines="1"
android:ellipsize="end"
android:textAlignment="viewStart"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
+ android:textAppearance="@style/Subhead"
android:paddingStart="6dp"
android:paddingBottom="1dp"/>
diff --git a/res/layout/item_photo_grid.xml b/res/layout/item_photo_grid.xml
index 562ebd3..5cf6850 100644
--- a/res/layout/item_photo_grid.xml
+++ b/res/layout/item_photo_grid.xml
@@ -112,6 +112,7 @@
android:pointerIcon="hand">
<ImageView
+ android:id="@+id/icon_id"
android:layout_height="@dimen/briefcase_icon_size_photo"
android:layout_width="@dimen/briefcase_icon_size_photo"
android:src="@drawable/ic_briefcase_white"
diff --git a/res/values-v31/dimens.xml b/res/values-v31/dimens.xml
deleted file mode 100644
index 15a7814..0000000
--- a/res/values-v31/dimens.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<!--
- ~ Copyright (C) 2021 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.
- -->
-<resources>
- <dimen name="action_bar_elevation">0dp</dimen>
- <dimen name="action_bar_margin">0dp</dimen>
-</resources>
diff --git a/res/values-v31/styles.xml b/res/values-v31/styles.xml
index bcdfa72..70ec383 100644
--- a/res/values-v31/styles.xml
+++ b/res/values-v31/styles.xml
@@ -16,7 +16,7 @@
-->
<resources>
- <style name="SectionHeader" parent="@*android:style/TextAppearance.DeviceDefault.Medium">
+ <style name="SectionHeader" parent="@android:style/TextAppearance.Material.Medium">
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="fontFamily">@string/config_fontFamilyMedium</item>
<item name="android:textSize">12sp</item>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 9828762..1a4d3bc 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -52,5 +52,4 @@
<color name="list_divider_color">#1f000000</color>
<color name="list_item_selected_background_color">?android:colorSecondary</color>
- <color name="color_surface_header">@color/app_background_color</color>
</resources>
diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml
index 31b3747..0b334d2 100644
--- a/res/values/overlayable.xml
+++ b/res/values/overlayable.xml
@@ -41,7 +41,6 @@
<!-- START COLOR -->
<item type="color" name="primary"/>
<item type="color" name="list_item_selected_background_color"/>
- <item type="color" name="color_surface_header"/>
<!-- END COLOR -->
<!-- START DIMEN -->
diff --git a/res/values/styles_text.xml b/res/values/styles_text.xml
index 6c38059..8ba56b1 100644
--- a/res/values/styles_text.xml
+++ b/res/values/styles_text.xml
@@ -19,7 +19,7 @@
<item name="android:textSize">11sp</item>
</style>
- <style name="SectionHeader" parent="@*android:style/TextAppearance.DeviceDefault.Medium">
+ <style name="SectionHeader" parent="@android:style/TextAppearance.Material.Medium">
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textAllCaps">true</item>
<item name="fontFamily">@string/config_fontFamilyMedium</item>
@@ -67,31 +67,32 @@
<item name="android:textSize">@dimen/action_mode_text_size</item>
</style>
- <style name="ToolbarTitle" parent="@*android:style/TextAppearance.DeviceDefault.Title">
+ <style name="ToolbarTitle" parent="@android:style/TextAppearance.Material.Title">
<item name="fontFamily">@string/config_fontFamilyMedium</item>
</style>
- <style name="DrawerMenuTitle" parent="@*android:style/TextAppearance.DeviceDefault.Title">
+ <style name="DrawerMenuTitle" parent="@android:style/TextAppearance.Material.Title">
<item name="android:textSize">24sp</item>
<item name="fontFamily">@string/config_fontFamilyMedium</item>
</style>
- <style name="DrawerMenuHeader" parent="@*android:style/TextAppearance.DeviceDefault.Subhead">
+ <style name="DrawerMenuHeader" parent="@android:style/TextAppearance.Material.Subhead">
<item name="android:textColor">?android:attr/textColorSecondary</item>
<item name="android:textAllCaps">true</item>
<item name="android:textSize">11sp</item>
<item name="fontFamily">@string/config_fontFamilyMedium</item>
</style>
- <style name="DrawerMenuPrimary" parent="*android:style/TextAppearance.DeviceDefault.Body2">
+ <style name="DrawerMenuPrimary" parent="android:style/TextAppearance.Material.Body2">
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/item_root_primary_text</item>
<item name="fontFamily">@string/config_fontFamilyMedium</item>
</style>
- <style name="DrawerMenuSecondary" parent="*android:style/TextAppearance.DeviceDefault.Body2">
+ <style name="DrawerMenuSecondary" parent="android:style/TextAppearance.Material.Body2">
<item name="android:textSize">12sp</item>
<item name="android:textColor">@color/item_root_secondary_text</item>
+ <item name="fontFamily">@string/config_fontFamily</item>
</style>
<style name="InspectorKeySubTitle" parent="@style/TextAppearance.MaterialComponents.Subtitle1">
@@ -126,19 +127,27 @@
<item name="fontFamily">@string/config_fontFamilyMedium</item>
</style>
- <style name="TabTextAppearance" parent="@*android:style/TextAppearance.DeviceDefault.Medium">
+ <style name="TabTextAppearance" parent="@android:style/TextAppearance.Material.Medium">
<item name="android:textSize">14sp</item>
<item name="fontFamily">@string/config_fontFamilyMedium</item>
</style>
- <style name="ItemCaptionText" parent="@*android:style/TextAppearance.DeviceDefault.Caption">
+ <style name="ItemCaptionText" parent="@android:style/TextAppearance.Material.Caption">
<item name="android:textColor">@color/doc_list_item_subtitle_color</item>
<item name="fontFamily">@string/config_fontFamily</item>
</style>
- <style name="MenuItemTextAppearance" parent="*android:style/TextAppearance.DeviceDefault.Body2">
+ <style name="MenuItemTextAppearance" parent="@android:style/TextAppearance.Material.Body2">
<item name="android:textSize">14sp</item>
<item name="fontFamily">@string/config_fontFamily</item>
</style>
+ <style name="Subhead" parent="@android:style/TextAppearance.Material.Subhead">
+ <item name="fontFamily">@string/config_fontFamily</item>
+ </style>
+
+ <style name="Body1" parent="@android:style/TextAppearance.Material.Body1">
+ <item name="fontFamily">@string/config_fontFamily</item>
+ </style>
+
</resources>
\ No newline at end of file
diff --git a/src/com/android/documentsui/BaseActivity.java b/src/com/android/documentsui/BaseActivity.java
index b4ab5bd..5efb9a9 100644
--- a/src/com/android/documentsui/BaseActivity.java
+++ b/src/com/android/documentsui/BaseActivity.java
@@ -167,11 +167,6 @@
mNavigator = new NavigationViewManager(this, mDrawer, mState, this, breadcrumb,
profileTabsContainer, DocumentsApplication.getUserIdManager(this));
- AppBarLayout appBarLayout = findViewById(R.id.app_bar);
- if (appBarLayout != null) {
- appBarLayout.addOnOffsetChangedListener(mNavigator);
- }
-
SearchManagerListener searchListener = new SearchManagerListener() {
/**
* Called when search results changed. Refreshes the content of the directory. It
diff --git a/src/com/android/documentsui/DevicePolicyResources.java b/src/com/android/documentsui/DevicePolicyResources.java
new file mode 100644
index 0000000..651441d
--- /dev/null
+++ b/src/com/android/documentsui/DevicePolicyResources.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2022 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.documentsui;
+
+import android.app.admin.DevicePolicyManager;
+
+/**
+ * Class containing the required identifiers to update device management resources.
+ *
+ * <p>See {@link DevicePolicyManager#getDrawable} and {@link DevicePolicyManager#getString}.
+ */
+public class DevicePolicyResources {
+
+ /**
+ * Class containing the identifiers used to update device management-related system strings.
+ */
+ public static final class Strings {
+ private static final String PREFIX = "DocumentsUi.";
+
+ /**
+ * An ID for any string that can't be updated.
+ */
+ public static final String UNDEFINED = "UNDEFINED";
+
+ /**
+ * Title for error message shown when work profile is turned off.
+ */
+ public static final String WORK_PROFILE_OFF_ERROR_TITLE =
+ PREFIX + "WORK_PROFILE_OFF_ERROR_TITLE";
+
+ /**
+ * Button text shown when work profile is turned off.
+ */
+ public static final String WORK_PROFILE_OFF_ENABLE_BUTTON =
+ PREFIX + "WORK_PROFILE_OFF_ENABLE_BUTTON";
+
+ /**
+ * Title for error message shown when a user's IT admin does not allow the user to
+ * select work files from a personal app.
+ */
+ public static final String CANT_SELECT_WORK_FILES_TITLE =
+ PREFIX + "CANT_SELECT_WORK_FILES_TITLE";
+
+ /**
+ * Message shown when a user's IT admin does not allow the user to select work files
+ * from a personal app.
+ */
+ public static final String CANT_SELECT_WORK_FILES_MESSAGE =
+ PREFIX + "CANT_SELECT_WORK_FILES_MESSAGE";
+
+ /**
+ * Title for error message shown when a user's IT admin does not allow the user to
+ * select personal files from a work app.
+ */
+ public static final String CANT_SELECT_PERSONAL_FILES_TITLE =
+ PREFIX + "CANT_SELECT_PERSONAL_FILES_TITLE";
+
+ /**
+ * Message shown when a user's IT admin does not allow the user to select personal files
+ * from a work app.
+ */
+ public static final String CANT_SELECT_PERSONAL_FILES_MESSAGE =
+ PREFIX + "CANT_SELECT_PERSONAL_FILES_MESSAGE";
+
+ /**
+ * Title for error message shown when a user's IT admin does not allow the user to save
+ * files from their personal profile to their work profile.
+ */
+ public static final String CANT_SAVE_TO_WORK_TITLE =
+ PREFIX + "CANT_SAVE_TO_WORK_TITLE";
+
+ /**
+ * Message shown when a user's IT admin does not allow the user to save files from their
+ * personal profile to their work profile.
+ */
+ public static final String CANT_SAVE_TO_WORK_MESSAGE =
+ PREFIX + "CANT_SAVE_TO_WORK_MESSAGE";
+
+ /**
+ * Title for error message shown when a user's IT admin does not allow the user to save
+ * files from their work profile to their personal profile.
+ */
+ public static final String CANT_SAVE_TO_PERSONAL_TITLE =
+ PREFIX + "CANT_SAVE_TO_PERSONAL_TITLE";
+
+ /**
+ * Message shown when a user's IT admin does not allow the user to save files from their
+ * work profile to their personal profile.
+ */
+ public static final String CANT_SAVE_TO_PERSONAL_MESSAGE =
+ PREFIX + "CANT_SAVE_TO_PERSONAL_MESSAGE";
+
+ /**
+ * Title for error message shown when a user tries to do something on their work
+ * device, but that action isn't allowed by their IT admin.
+ */
+ public static final String CROSS_PROFILE_NOT_ALLOWED_TITLE =
+ PREFIX + "CROSS_PROFILE_NOT_ALLOWED_TITLE";
+
+ /**
+ * Message shown when a user tries to do something on their work device, but that action
+ * isn't allowed by their IT admin.
+ */
+ public static final String CROSS_PROFILE_NOT_ALLOWED_MESSAGE =
+ PREFIX + "CROSS_PROFILE_NOT_ALLOWED_MESSAGE";
+
+ /**
+ * Content description text that's spoken by a screen reader for previewing a work file
+ * before opening it. Accepts file name as a param.
+ */
+ public static final String PREVIEW_WORK_FILE_ACCESSIBILITY =
+ PREFIX + "PREVIEW_WORK_FILE_ACCESSIBILITY";
+
+ /**
+ * Label for tab and sidebar to indicate personal content.
+ */
+ public static final String PERSONAL_TAB = PREFIX + "PERSONAL_TAB";
+
+ /**
+ * Label for tab and sidebar tab to indicate work content
+ */
+ public static final String WORK_TAB = PREFIX + "WORK_TAB";
+
+ }
+
+ /**
+ * Class containing the identifiers used to update device management-related system drawable.
+ */
+ public static final class Drawables {
+ /**
+ * Specifically used to badge work profile app icons.
+ */
+ public static final String WORK_PROFILE_ICON_BADGE = "WORK_PROFILE_ICON_BADGE";
+
+ /**
+ * General purpose work profile icon (i.e. generic icon badging). For badging app icons
+ * specifically, see {@link #WORK_PROFILE_ICON_BADGE}.
+ */
+ public static final String WORK_PROFILE_ICON = "WORK_PROFILE_ICON";
+
+ /**
+ * General purpose icon representing the work profile off state.
+ */
+ public static final String WORK_PROFILE_OFF_ICON = "WORK_PROFILE_OFF_ICON";
+
+ /**
+ * General purpose icon for the work profile user avatar.
+ */
+ public static final String WORK_PROFILE_USER_ICON = "WORK_PROFILE_USER_ICON";
+
+ /**
+ * Class containing the style identifiers used to update device management-related system
+ * drawable.
+ */
+ public static final class Style {
+
+ /**
+ * A style identifier indicating that the updatable drawable should use the default
+ * style.
+ */
+ public static final String DEFAULT = "DEFAULT";
+
+ /**
+ * A style identifier indicating that the updatable drawable has a solid color fill.
+ */
+ public static final String SOLID_COLORED = "SOLID_COLORED";
+
+ /**
+ * A style identifier indicating that the updatable drawable has a solid non-colored
+ * fill.
+ */
+ public static final String SOLID_NOT_COLORED = "SOLID_NOT_COLORED";
+
+ /**
+ * A style identifier indicating that the updatable drawable is an outline.
+ */
+ public static final String OUTLINE = "OUTLINE";
+ }
+ }
+}
diff --git a/src/com/android/documentsui/NavigationViewManager.java b/src/com/android/documentsui/NavigationViewManager.java
index 83979ab..b09b3c0 100644
--- a/src/com/android/documentsui/NavigationViewManager.java
+++ b/src/com/android/documentsui/NavigationViewManager.java
@@ -19,27 +19,20 @@
import static com.android.documentsui.base.SharedMinimal.VERBOSE;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.Outline;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
import android.view.ViewOutlineProvider;
-import android.view.Window;
-import android.view.WindowManager;
import android.widget.FrameLayout;
-import androidx.annotation.ColorRes;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
-import androidx.core.content.ContextCompat;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.base.UserId;
import com.android.documentsui.dirlist.AnimationView;
-import com.android.documentsui.util.VersionUtils;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
@@ -49,13 +42,12 @@
/**
* A facade over the portions of the app and drawer toolbars.
*/
-public class NavigationViewManager implements AppBarLayout.OnOffsetChangedListener {
+public class NavigationViewManager {
private static final String TAG = "NavigationViewManager";
private final DrawerController mDrawer;
private final Toolbar mToolbar;
- private final BaseActivity mActivity;
private final View mHeader;
private final State mState;
private final NavigationViewManager.Environment mEnv;
@@ -69,7 +61,6 @@
private final boolean mShowSearchBar;
private boolean mIsActionModeActivated = false;
- private @ColorRes int mDefaultStatusBarColorResId;
public NavigationViewManager(
BaseActivity activity,
@@ -80,7 +71,6 @@
View tabLayoutContainer,
UserIdManager userIdManager) {
- mActivity = activity;
mToolbar = activity.findViewById(R.id.toolbar);
mHeader = activity.findViewById(R.id.directory_header);
mDrawer = drawer;
@@ -103,15 +93,6 @@
mDefaultOutlineProvider = mToolbar.getOutlineProvider();
mShowSearchBar = activity.getResources().getBoolean(R.bool.show_search_bar);
- final int[] styledAttrs = {android.R.attr.statusBarColor};
- TypedArray a = mActivity.obtainStyledAttributes(styledAttrs);
- mDefaultStatusBarColorResId = a.getResourceId(0, -1);
- if (mDefaultStatusBarColorResId == -1) {
- Log.w(TAG, "Retrieve statusBarColorResId from theme failed, assigned default");
- mDefaultStatusBarColorResId = R.color.app_background_color;
- }
- a.recycle();
-
final Resources resources = mToolbar.getResources();
final int radius = resources.getDimensionPixelSize(R.dimen.search_bar_radius);
final int marginStart =
@@ -127,36 +108,6 @@
};
}
- @Override
- public void onOffsetChanged(AppBarLayout appBarLayout, int offset) {
- if (!VersionUtils.isAtLeastS()) {
- return;
- }
-
- // For S+ Only. Change toolbar color dynamically based on scroll offset.
- // Usually this can be done in xml using app:contentScrim and app:statusBarScrim, however
- // in our case since we also put directory_header.xml inside the CollapsingToolbarLayout,
- // the scrim will also cover the directory header. Long term need to think about how to
- // move directory_header out of the AppBarLayout.
-
- Window window = mActivity.getWindow();
- View actionBar = window.getDecorView().findViewById(R.id.action_mode_bar);
- int dynamicHeaderColor = ContextCompat.getColor(mActivity,
- offset == 0 ? mDefaultStatusBarColorResId : R.color.color_surface_header);
- if (actionBar != null) {
- // Action bar needs to be updated separately for selection mode.
- actionBar.setBackgroundColor(dynamicHeaderColor);
- }
-
- window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- window.setStatusBarColor(dynamicHeaderColor);
- if (shouldShowSearchBar()) {
- // Do not change search bar background.
- } else {
- mToolbar.setBackground(new ColorDrawable(dynamicHeaderColor));
- }
- }
-
public void setSearchBarClickListener(View.OnClickListener listener) {
mSearchBarView.setOnClickListener(listener);
}
diff --git a/src/com/android/documentsui/ProfileTabs.java b/src/com/android/documentsui/ProfileTabs.java
index 7149de6..6c2b1dd 100644
--- a/src/com/android/documentsui/ProfileTabs.java
+++ b/src/com/android/documentsui/ProfileTabs.java
@@ -18,14 +18,21 @@
import static androidx.core.util.Preconditions.checkNotNull;
+import static com.android.documentsui.DevicePolicyResources.Strings.PERSONAL_TAB;
+import static com.android.documentsui.DevicePolicyResources.Strings.WORK_TAB;
+
+import android.app.admin.DevicePolicyManager;
+import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.base.UserId;
+import com.android.modules.utils.build.SdkLevel;
import com.google.android.material.tabs.TabLayout;
import com.google.common.base.Objects;
@@ -112,14 +119,33 @@
mTabs.removeAllTabs();
if (mUserIds.size() > 1) {
// set setSelected to false otherwise it will trigger callback.
- mTabs.addTab(createTab(R.string.personal_tab,
+ mTabs.addTab(createTab(
+ getEnterpriseString(PERSONAL_TAB, R.string.personal_tab),
mUserIdManager.getSystemUser()), /* setSelected= */false);
- mTabs.addTab(createTab(R.string.work_tab,
+ mTabs.addTab(createTab(
+ getEnterpriseString(WORK_TAB, R.string.work_tab),
mUserIdManager.getManagedUser()), /* setSelected= */false);
}
}
}
+ private String getEnterpriseString(String updatableStringId, int defaultStringId) {
+ if (SdkLevel.isAtLeastT()) {
+ return getUpdatableEnterpriseString(updatableStringId, defaultStringId);
+ } else {
+ return mTabsContainer.getContext().getString(defaultStringId);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private String getUpdatableEnterpriseString(String updatableStringId, int defaultStringId) {
+ DevicePolicyManager dpm = mTabsContainer.getContext().getSystemService(
+ DevicePolicyManager.class);
+ return dpm.getResources().getString(
+ updatableStringId,
+ () -> mTabsContainer.getContext().getString(defaultStringId));
+ }
+
/**
* Returns the user represented by the selected tab. If there is no tab, return the
* current user.
@@ -145,8 +171,8 @@
&& mState.stack.getRoot() != null && mState.stack.getRoot().supportsCrossProfile();
}
- private TabLayout.Tab createTab(int resId, UserId userId) {
- return mTabs.newTab().setText(resId).setTag(userId);
+ private TabLayout.Tab createTab(String text, UserId userId) {
+ return mTabs.newTab().setText(text).setTag(userId);
}
@Override
diff --git a/src/com/android/documentsui/dirlist/DocumentHolder.java b/src/com/android/documentsui/dirlist/DocumentHolder.java
index 7962f7f..5e38b48 100644
--- a/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -16,8 +16,13 @@
package com.android.documentsui.dirlist;
+import static com.android.documentsui.DevicePolicyResources.Strings.PREVIEW_WORK_FILE_ACCESSIBILITY;
+import static com.android.documentsui.DevicePolicyResources.Strings.UNDEFINED;
+
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.database.Cursor;
+import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -27,11 +32,14 @@
import android.view.ViewPropertyAnimator;
import android.widget.ImageView;
+import androidx.annotation.RequiresApi;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.recyclerview.widget.RecyclerView;
+import com.android.documentsui.R;
import com.android.documentsui.base.Shared;
import com.android.documentsui.base.State;
+import com.android.modules.utils.build.SdkLevel;
import java.util.function.Function;
@@ -171,6 +179,29 @@
return view.animate().setDuration(Shared.CHECK_ANIMATION_DURATION).alpha(alpha);
}
+ protected String getPreviewIconContentDescription(boolean isWorkProfile, String fileName) {
+ if (SdkLevel.isAtLeastT()) {
+ return getUpdatablePreviewIconContentDescription(isWorkProfile, fileName);
+ } else {
+ return itemView.getResources().getString(
+ isWorkProfile ? R.string.preview_work_file : R.string.preview_file, fileName);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private String getUpdatablePreviewIconContentDescription(
+ boolean isWorkProfile, String fileName) {
+ DevicePolicyManager dpm = itemView.getContext().getSystemService(
+ DevicePolicyManager.class);
+ String updatableStringId = isWorkProfile ? PREVIEW_WORK_FILE_ACCESSIBILITY : UNDEFINED;
+ int defaultStringId =
+ isWorkProfile ? R.string.preview_work_file : R.string.preview_file;
+ return dpm.getResources().getString(
+ updatableStringId,
+ () -> itemView.getResources().getString(defaultStringId, fileName),
+ /* formatArgs= */ fileName);
+ }
+
protected static class PreviewAccessibilityDelegate extends View.AccessibilityDelegate {
private Function<View, Boolean> mCallback;
diff --git a/src/com/android/documentsui/dirlist/GridDirectoryHolder.java b/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
index 930773b..d66e7da 100644
--- a/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
+++ b/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
@@ -16,10 +16,15 @@
package com.android.documentsui.dirlist;
+import static com.android.documentsui.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
+import static com.android.documentsui.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
import static com.android.documentsui.base.DocumentInfo.getCursorString;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.view.MotionEvent;
@@ -28,10 +33,13 @@
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.RequiresApi;
+
import com.android.documentsui.IconUtils;
import com.android.documentsui.R;
import com.android.documentsui.base.State;
import com.android.documentsui.ui.Views;
+import com.android.modules.utils.build.SdkLevel;
final class GridDirectoryHolder extends DocumentHolder {
@@ -52,6 +60,18 @@
mIconBriefcase = (ImageView) itemView.findViewById(R.id.icon_briefcase);
mIconMime.setImageDrawable(
IconUtils.loadMimeIcon(context, DocumentsContract.Document.MIME_TYPE_DIR));
+
+ if (SdkLevel.isAtLeastT()) {
+ setUpdatableWorkProfileIcon(context);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private void setUpdatableWorkProfileIcon(Context context) {
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ Drawable drawable = dpm.getResources().getDrawable(WORK_PROFILE_ICON, SOLID_COLORED, () ->
+ context.getDrawable(R.drawable.ic_briefcase));
+ mIconBriefcase.setImageDrawable(drawable);
}
@Override
diff --git a/src/com/android/documentsui/dirlist/GridDocumentHolder.java b/src/com/android/documentsui/dirlist/GridDocumentHolder.java
index 631298f..b3a5d07 100644
--- a/src/com/android/documentsui/dirlist/GridDocumentHolder.java
+++ b/src/com/android/documentsui/dirlist/GridDocumentHolder.java
@@ -16,12 +16,17 @@
package com.android.documentsui.dirlist;
+import static com.android.documentsui.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
+import static com.android.documentsui.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
import static com.android.documentsui.base.DocumentInfo.getCursorInt;
import static com.android.documentsui.base.DocumentInfo.getCursorLong;
import static com.android.documentsui.base.DocumentInfo.getCursorString;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.provider.DocumentsContract.Document;
import android.text.format.Formatter;
import android.view.MotionEvent;
@@ -30,12 +35,15 @@
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.RequiresApi;
+
import com.android.documentsui.R;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.Shared;
import com.android.documentsui.base.UserId;
import com.android.documentsui.roots.RootCursorWrapper;
import com.android.documentsui.ui.Views;
+import com.android.modules.utils.build.SdkLevel;
import java.util.function.Function;
@@ -71,6 +79,18 @@
mPreviewIcon = itemView.findViewById(R.id.preview_icon);
mIconHelper = iconHelper;
+
+ if (SdkLevel.isAtLeastT()) {
+ setUpdatableWorkProfileIcon(context);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private void setUpdatableWorkProfileIcon(Context context) {
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ Drawable drawable = dpm.getResources().getDrawable(WORK_PROFILE_ICON, SOLID_COLORED, () ->
+ context.getDrawable(R.drawable.ic_briefcase));
+ mIconBriefcase.setImageDrawable(drawable);
}
@Override
@@ -116,10 +136,9 @@
mPreviewIcon.setVisibility(show ? View.VISIBLE : View.GONE);
if (show) {
mPreviewIcon.setContentDescription(
- itemView.getResources().getString(
- mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier())
- ? R.string.preview_work_file
- : R.string.preview_file, mDoc.displayName));
+ getPreviewIconContentDescription(
+ mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier()),
+ mDoc.displayName));
mPreviewIcon.setAccessibilityDelegate(new PreviewAccessibilityDelegate(clickCallback));
}
}
diff --git a/src/com/android/documentsui/dirlist/GridPhotoHolder.java b/src/com/android/documentsui/dirlist/GridPhotoHolder.java
index b415eba..98cebe8 100644
--- a/src/com/android/documentsui/dirlist/GridPhotoHolder.java
+++ b/src/com/android/documentsui/dirlist/GridPhotoHolder.java
@@ -16,12 +16,17 @@
package com.android.documentsui.dirlist;
+import static com.android.documentsui.DevicePolicyResources.Drawables.Style.SOLID_NOT_COLORED;
+import static com.android.documentsui.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
import static com.android.documentsui.base.DocumentInfo.getCursorInt;
import static com.android.documentsui.base.DocumentInfo.getCursorLong;
import static com.android.documentsui.base.DocumentInfo.getCursorString;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.provider.DocumentsContract.Document;
import android.text.format.Formatter;
import android.view.MotionEvent;
@@ -29,12 +34,15 @@
import android.view.ViewGroup;
import android.widget.ImageView;
+import androidx.annotation.RequiresApi;
+
import com.android.documentsui.R;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.Shared;
import com.android.documentsui.base.UserId;
import com.android.documentsui.roots.RootCursorWrapper;
import com.android.documentsui.ui.Views;
+import com.android.modules.utils.build.SdkLevel;
import java.util.function.Function;
@@ -60,6 +68,21 @@
mPreviewIcon = itemView.findViewById(R.id.preview_icon);
mIconHelper = iconHelper;
+
+ if (SdkLevel.isAtLeastT()) {
+ setUpdatableWorkProfileIcon(context);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private void setUpdatableWorkProfileIcon(Context context) {
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ Drawable drawable = dpm.getResources().getDrawable(
+ WORK_PROFILE_ICON, SOLID_NOT_COLORED, () ->
+ context.getDrawable(R.drawable.ic_briefcase));
+ ImageView icon = (ImageView) mIconBriefcase.findViewById(R.id.icon_id);
+
+ icon.setImageDrawable(drawable);
}
@Override
@@ -98,10 +121,9 @@
mPreviewIcon.setVisibility(show ? View.VISIBLE : View.GONE);
if (show) {
mPreviewIcon.setContentDescription(
- itemView.getResources().getString(
- mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier())
- ? R.string.preview_work_file
- : R.string.preview_file, mDoc.displayName));
+ getPreviewIconContentDescription(
+ mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier()),
+ mDoc.displayName));
mPreviewIcon.setAccessibilityDelegate(new PreviewAccessibilityDelegate(clickCallback));
}
}
diff --git a/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index f6a9002..0e10755 100644
--- a/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -16,12 +16,17 @@
package com.android.documentsui.dirlist;
+import static com.android.documentsui.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
+import static com.android.documentsui.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
import static com.android.documentsui.base.DocumentInfo.getCursorInt;
import static com.android.documentsui.base.DocumentInfo.getCursorString;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
@@ -33,6 +38,7 @@
import android.widget.TextView;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import com.android.documentsui.R;
import com.android.documentsui.base.DocumentInfo;
@@ -42,6 +48,7 @@
import com.android.documentsui.base.UserId;
import com.android.documentsui.roots.RootCursorWrapper;
import com.android.documentsui.ui.Views;
+import com.android.modules.utils.build.SdkLevel;
import java.util.ArrayList;
import java.util.function.Function;
@@ -90,6 +97,18 @@
mIconHelper = iconHelper;
mFileTypeLookup = fileTypeLookup;
mDoc = new DocumentInfo();
+
+ if (SdkLevel.isAtLeastT()) {
+ setUpdatableWorkProfileIcon(context);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private void setUpdatableWorkProfileIcon(Context context) {
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ Drawable drawable = dpm.getResources().getDrawable(WORK_PROFILE_ICON, SOLID_COLORED, () ->
+ context.getDrawable(R.drawable.ic_briefcase));
+ mIconBriefcase.setImageDrawable(drawable);
}
@Override
@@ -137,10 +156,9 @@
mPreviewIcon.setVisibility(show ? View.VISIBLE : View.GONE);
if (show) {
mPreviewIcon.setContentDescription(
- itemView.getResources().getString(
- mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier())
- ? R.string.preview_work_file
- : R.string.preview_file, mDoc.displayName));
+ getPreviewIconContentDescription(
+ mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier()),
+ mDoc.displayName));
mPreviewIcon.setAccessibilityDelegate(
new PreviewAccessibilityDelegate(clickCallback));
}
diff --git a/src/com/android/documentsui/dirlist/Message.java b/src/com/android/documentsui/dirlist/Message.java
index 371daee..ccdad46 100644
--- a/src/com/android/documentsui/dirlist/Message.java
+++ b/src/com/android/documentsui/dirlist/Message.java
@@ -16,13 +16,30 @@
package com.android.documentsui.dirlist;
+import static com.android.documentsui.DevicePolicyResources.Drawables.Style.OUTLINE;
+import static com.android.documentsui.DevicePolicyResources.Drawables.WORK_PROFILE_OFF_ICON;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SAVE_TO_PERSONAL_MESSAGE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SAVE_TO_PERSONAL_TITLE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SAVE_TO_WORK_MESSAGE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SAVE_TO_WORK_TITLE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SELECT_PERSONAL_FILES_MESSAGE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SELECT_PERSONAL_FILES_TITLE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SELECT_WORK_FILES_MESSAGE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SELECT_WORK_FILES_TITLE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CROSS_PROFILE_NOT_ALLOWED_MESSAGE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CROSS_PROFILE_NOT_ALLOWED_TITLE;
+import static com.android.documentsui.DevicePolicyResources.Strings.WORK_PROFILE_OFF_ENABLE_BUTTON;
+import static com.android.documentsui.DevicePolicyResources.Strings.WORK_PROFILE_OFF_ERROR_TITLE;
+
import android.Manifest;
import android.app.AuthenticationRequiredException;
+import android.app.admin.DevicePolicyManager;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import com.android.documentsui.CrossProfileException;
import com.android.documentsui.CrossProfileNoPermissionException;
@@ -35,6 +52,7 @@
import com.android.documentsui.base.State;
import com.android.documentsui.base.UserId;
import com.android.documentsui.dirlist.DocumentsAdapter.Environment;
+import com.android.modules.utils.build.SdkLevel;
/**
* Data object used by {@link InflateMessageDocumentHolder} and {@link HeaderMessageDocumentHolder}.
@@ -217,20 +235,21 @@
mLayout = InflateMessageDocumentHolder.LAYOUT_CROSS_PROFILE_ERROR;
CharSequence buttonText = null;
if (mCanModifyQuietMode) {
- buttonText = mEnv.getContext().getResources().getText(R.string.quiet_mode_button);
+ buttonText = getEnterpriseString(
+ WORK_PROFILE_OFF_ENABLE_BUTTON, R.string.quiet_mode_button);
mCallback = () -> mEnv.getActionHandler().requestQuietModeDisabled(
mEnv.getDisplayState().stack.getRoot(), userId);
}
update(
- mEnv.getContext().getResources().getText(R.string.quiet_mode_error_title),
+ getEnterpriseString(
+ WORK_PROFILE_OFF_ERROR_TITLE, R.string.quiet_mode_error_title),
/* messageString= */ "",
buttonText,
- mEnv.getContext().getDrawable(R.drawable.work_off));
+ getWorkProfileOffIcon());
}
private void updateToCrossProfileNoPermissionErrorMessage() {
mLayout = InflateMessageDocumentHolder.LAYOUT_CROSS_PROFILE_ERROR;
- boolean currentUserIsSystem = UserId.CURRENT_USER.isSystem();
update(getCrossProfileNoPermissionErrorTitle(),
getCrossProfileNoPermissionErrorMessage(),
/* buttonString= */ null,
@@ -239,38 +258,55 @@
private CharSequence getCrossProfileNoPermissionErrorTitle() {
boolean currentUserIsSystem = UserId.CURRENT_USER.isSystem();
- Resources res = mEnv.getContext().getResources();
switch (mEnv.getDisplayState().action) {
case State.ACTION_GET_CONTENT:
case State.ACTION_OPEN:
case State.ACTION_OPEN_TREE:
- return res.getText(currentUserIsSystem
- ? R.string.cant_select_work_files_error_title
- : R.string.cant_select_personal_files_error_title);
+ return currentUserIsSystem
+ ? getEnterpriseString(
+ CANT_SELECT_WORK_FILES_TITLE,
+ R.string.cant_select_work_files_error_title)
+ : getEnterpriseString(
+ CANT_SELECT_PERSONAL_FILES_TITLE,
+ R.string.cant_select_personal_files_error_title);
case State.ACTION_CREATE:
- return res.getText(currentUserIsSystem
- ? R.string.cant_save_to_work_error_title
- : R.string.cant_save_to_personal_error_title);
+ return currentUserIsSystem
+ ? getEnterpriseString(
+ CANT_SAVE_TO_WORK_TITLE, R.string.cant_save_to_work_error_title)
+ : getEnterpriseString(
+ CANT_SAVE_TO_PERSONAL_TITLE,
+ R.string.cant_save_to_personal_error_title);
}
- return res.getText(R.string.cross_profile_action_not_allowed_title);
+ return getEnterpriseString(
+ CROSS_PROFILE_NOT_ALLOWED_TITLE,
+ R.string.cross_profile_action_not_allowed_title);
}
private CharSequence getCrossProfileNoPermissionErrorMessage() {
boolean currentUserIsSystem = UserId.CURRENT_USER.isSystem();
- Resources res = mEnv.getContext().getResources();
switch (mEnv.getDisplayState().action) {
case State.ACTION_GET_CONTENT:
case State.ACTION_OPEN:
case State.ACTION_OPEN_TREE:
- return res.getText(currentUserIsSystem
- ? R.string.cant_select_work_files_error_message
- : R.string.cant_select_personal_files_error_message);
+ return currentUserIsSystem
+ ? getEnterpriseString(
+ CANT_SELECT_WORK_FILES_MESSAGE,
+ R.string.cant_select_work_files_error_message)
+ : getEnterpriseString(
+ CANT_SELECT_PERSONAL_FILES_MESSAGE,
+ R.string.cant_select_personal_files_error_message);
case State.ACTION_CREATE:
- return res.getText(currentUserIsSystem
- ? R.string.cant_save_to_work_error_message
- : R.string.cant_save_to_personal_error_message);
+ return currentUserIsSystem
+ ? getEnterpriseString(
+ CANT_SAVE_TO_WORK_MESSAGE,
+ R.string.cant_save_to_work_error_message)
+ : getEnterpriseString(
+ CANT_SAVE_TO_PERSONAL_MESSAGE,
+ R.string.cant_save_to_personal_error_message);
}
- return res.getText(R.string.cross_profile_action_not_allowed_message);
+ return getEnterpriseString(
+ CROSS_PROFILE_NOT_ALLOWED_MESSAGE,
+ R.string.cross_profile_action_not_allowed_message);
}
private void updateToInflatedErrorMessage() {
@@ -295,5 +331,38 @@
}
update(null, message, null, mEnv.getContext().getDrawable(R.drawable.empty));
}
+
+ private String getEnterpriseString(String updatableStringId, int defaultStringId) {
+ if (SdkLevel.isAtLeastT()) {
+ return getUpdatableEnterpriseString(updatableStringId, defaultStringId);
+ } else {
+ return mEnv.getContext().getString(defaultStringId);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private String getUpdatableEnterpriseString(String updatableStringId, int defaultStringId) {
+ DevicePolicyManager dpm = mEnv.getContext().getSystemService(
+ DevicePolicyManager.class);
+ return dpm.getResources().getString(
+ updatableStringId, () -> mEnv.getContext().getString(defaultStringId));
+ }
+
+ private Drawable getWorkProfileOffIcon() {
+ if (SdkLevel.isAtLeastT()) {
+ return getUpdatableWorkProfileIcon();
+ } else {
+ return mEnv.getContext().getDrawable(R.drawable.work_off);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private Drawable getUpdatableWorkProfileIcon() {
+ DevicePolicyManager dpm = mEnv.getContext().getSystemService(
+ DevicePolicyManager.class);
+ return dpm.getResources().getDrawable(
+ WORK_PROFILE_OFF_ICON, OUTLINE,
+ () -> mEnv.getContext().getDrawable(R.drawable.work_off));
+ }
}
}
diff --git a/src/com/android/documentsui/sidebar/RootsFragment.java b/src/com/android/documentsui/sidebar/RootsFragment.java
index de6c18d..5bf3f1a 100644
--- a/src/com/android/documentsui/sidebar/RootsFragment.java
+++ b/src/com/android/documentsui/sidebar/RootsFragment.java
@@ -20,11 +20,11 @@
import static com.android.documentsui.base.SharedMinimal.DEBUG;
import static com.android.documentsui.base.SharedMinimal.VERBOSE;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
@@ -273,7 +273,7 @@
}
List<Item> sortedItems = sortLoadResult(
- getResources(),
+ getContext(),
state,
roots,
excludePackage,
@@ -347,7 +347,7 @@
*/
@VisibleForTesting
List<Item> sortLoadResult(
- Resources resources,
+ Context context,
State state,
Collection<RootInfo> roots,
@Nullable String excludePackage,
@@ -418,7 +418,8 @@
}
}
- List<Item> presentableList = new UserItemsCombiner(resources, state)
+ List<Item> presentableList = new UserItemsCombiner(
+ context.getResources(), context.getSystemService(DevicePolicyManager.class), state)
.setRootListForCurrentUser(rootList)
.setRootListForOtherUser(rootListOtherUser)
.createPresentableList();
diff --git a/src/com/android/documentsui/sidebar/UserItemsCombiner.java b/src/com/android/documentsui/sidebar/UserItemsCombiner.java
index 8bce7ce..1a68ca7 100644
--- a/src/com/android/documentsui/sidebar/UserItemsCombiner.java
+++ b/src/com/android/documentsui/sidebar/UserItemsCombiner.java
@@ -16,16 +16,23 @@
package com.android.documentsui.sidebar;
-import android.content.res.Resources;
-
import static androidx.core.util.Preconditions.checkArgument;
import static androidx.core.util.Preconditions.checkNotNull;
+import static com.android.documentsui.DevicePolicyResources.Strings.PERSONAL_TAB;
+import static com.android.documentsui.DevicePolicyResources.Strings.WORK_TAB;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.res.Resources;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import com.android.documentsui.R;
import com.android.documentsui.base.State;
import com.android.documentsui.base.UserId;
+import com.android.modules.utils.build.SdkLevel;
import java.util.ArrayList;
import java.util.List;
@@ -38,13 +45,15 @@
private UserId mCurrentUser;
private final Resources mResources;
+ private final DevicePolicyManager mDpm;
private final State mState;
private List<Item> mRootList;
private List<Item> mRootListOtherUser;
- UserItemsCombiner(Resources resources, State state) {
+ UserItemsCombiner(Resources resources, DevicePolicyManager dpm, State state) {
mCurrentUser = UserId.CURRENT_USER;
mResources = checkNotNull(resources);
+ mDpm = dpm;
mState = checkNotNull(state);
}
@@ -85,9 +94,10 @@
personalRootList = mRootListOtherUser;
workRootList = mRootList;
}
- result.add(new HeaderItem(mResources.getString(R.string.personal_tab)));
+ result.add(new HeaderItem(getEnterpriseString(
+ PERSONAL_TAB, R.string.personal_tab)));
result.addAll(personalRootList);
- result.add(new HeaderItem(mResources.getString(R.string.work_tab)));
+ result.add(new HeaderItem(getEnterpriseString(WORK_TAB, R.string.work_tab)));
result.addAll(workRootList);
} else {
result.addAll(mRootList);
@@ -98,4 +108,18 @@
}
return result;
}
+
+ private String getEnterpriseString(String updatableStringId, int defaultStringId) {
+ if (SdkLevel.isAtLeastT()) {
+ return getUpdatableEnterpriseString(updatableStringId, defaultStringId);
+ } else {
+ return mResources.getString(defaultStringId);
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private String getUpdatableEnterpriseString(String updatableStringId, int defaultStringId) {
+ return mDpm.getResources().getString(
+ updatableStringId, () -> mResources.getString(defaultStringId));
+ }
}
diff --git a/src/com/android/documentsui/util/VersionUtils.java b/src/com/android/documentsui/util/VersionUtils.java
index aba6374..c7926ad 100644
--- a/src/com/android/documentsui/util/VersionUtils.java
+++ b/src/com/android/documentsui/util/VersionUtils.java
@@ -16,7 +16,7 @@
package com.android.documentsui.util;
-import android.os.Build;
+import com.android.modules.utils.build.SdkLevel;
/**
* A utility class for checking Android version.
@@ -31,15 +31,13 @@
*/
public static boolean isAtLeastR() {
return isAtLeastS() // Keep reference to isAtLeastS() so it's not stripped from test apk
- || Build.VERSION.CODENAME.equals("R")
- || Build.VERSION.SDK_INT >= 30;
+ || SdkLevel.isAtLeastR();
}
/**
* Returns whether the device is running on Android S or newer.
*/
public static boolean isAtLeastS() {
- return Build.VERSION.CODENAME.equals("S")
- || Build.VERSION.SDK_INT >= 31;
+ return SdkLevel.isAtLeastS();
}
}
diff --git a/tests/functional/com/android/documentsui/DialogUiTest.java b/tests/functional/com/android/documentsui/DialogUiTest.java
index 90569ae..c9c9a77 100644
--- a/tests/functional/com/android/documentsui/DialogUiTest.java
+++ b/tests/functional/com/android/documentsui/DialogUiTest.java
@@ -29,6 +29,8 @@
import android.graphics.Paint;
import android.os.Build;
import android.os.ParcelFileDescriptor;
+import android.support.test.uiautomator.UiDevice;
+import android.view.KeyEvent;
import androidx.fragment.app.FragmentManager;
import androidx.test.filters.LargeTest;
@@ -75,6 +77,10 @@
mFileActivityIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager();
mScreenDensitySession = new ScreenDensitySession();
+
+ final UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ device.pressKeyCode(KeyEvent.KEYCODE_WAKEUP);
+ device.pressKeyCode(KeyEvent.KEYCODE_MENU);
}
@After
diff --git a/tests/functional/com/android/documentsui/FileCopyUiTest.java b/tests/functional/com/android/documentsui/FileCopyUiTest.java
index a4ee4d6..86b8acf 100644
--- a/tests/functional/com/android/documentsui/FileCopyUiTest.java
+++ b/tests/functional/com/android/documentsui/FileCopyUiTest.java
@@ -29,6 +29,7 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.provider.MediaStore;
import android.provider.Settings;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.text.TextUtils;
@@ -131,6 +132,7 @@
mPreTestStayAwakeValue = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
device.executeShellCommand("settings put global stay_on_while_plugged_in 3");
+ MediaStore.waitForIdle(context.getContentResolver());
mDeviceLabel = Settings.Global.getString(context.getContentResolver(),
Settings.Global.DEVICE_NAME);
diff --git a/tests/unit/com/android/documentsui/dirlist/MessageTest.java b/tests/unit/com/android/documentsui/dirlist/MessageTest.java
index 54dbbc5..0816684 100644
--- a/tests/unit/com/android/documentsui/dirlist/MessageTest.java
+++ b/tests/unit/com/android/documentsui/dirlist/MessageTest.java
@@ -16,11 +16,20 @@
package com.android.documentsui.dirlist;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SELECT_WORK_FILES_MESSAGE;
+import static com.android.documentsui.DevicePolicyResources.Strings.CANT_SELECT_WORK_FILES_TITLE;
+import static com.android.documentsui.DevicePolicyResources.Strings.WORK_PROFILE_OFF_ENABLE_BUTTON;
+import static com.android.documentsui.DevicePolicyResources.Strings.WORK_PROFILE_OFF_ERROR_TITLE;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyResourcesManager;
import android.content.Context;
import android.os.UserManager;
@@ -37,6 +46,7 @@
import com.android.documentsui.testing.TestActionHandler;
import com.android.documentsui.testing.TestEnv;
import com.android.documentsui.testing.UserManagers;
+import com.android.modules.utils.build.SdkLevel;
import org.junit.Before;
import org.junit.Test;
@@ -50,6 +60,7 @@
private Runnable mDefaultCallback = () -> {
};
private UserManager mUserManager;
+ private DevicePolicyManager mDevicePolicyManager;
private TestActionHandler mTestActionHandler;
@Before
@@ -57,7 +68,12 @@
mContext = mock(Context.class);
mUserManager = UserManagers.create();
mTestActionHandler = new TestActionHandler();
+ mDevicePolicyManager = mock(DevicePolicyManager.class);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mContext.getSystemServiceName(DevicePolicyManager.class))
+ .thenReturn(Context.DEVICE_POLICY_SERVICE);
+ when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
+ .thenReturn(mDevicePolicyManager);
when(mContext.getResources()).thenReturn(
InstrumentationRegistry.getInstrumentation().getTargetContext().getResources());
DocumentsAdapter.Environment env =
@@ -73,8 +89,20 @@
Model.Update error = new Model.Update(
new CrossProfileNoPermissionException(),
/* isRemoteActionsEnabled= */ true);
+ if (SdkLevel.isAtLeastT()) {
+ String title = mContext.getString(R.string.cant_select_work_files_error_title);
+ String message = mContext.getString(R.string.cant_select_work_files_error_message);
+ DevicePolicyResourcesManager devicePolicyResourcesManager = mock(
+ DevicePolicyResourcesManager.class);
+ when(mDevicePolicyManager.getResources()).thenReturn(devicePolicyResourcesManager);
+ when(devicePolicyResourcesManager.getString(eq(CANT_SELECT_WORK_FILES_TITLE), any()))
+ .thenReturn(title);
+ when(devicePolicyResourcesManager.getString(eq(CANT_SELECT_WORK_FILES_MESSAGE), any()))
+ .thenReturn(message);
+ }
mInflateMessage.update(error);
+
assertThat(mInflateMessage.getLayout())
.isEqualTo(InflateMessageDocumentHolder.LAYOUT_CROSS_PROFILE_ERROR);
assertThat(mInflateMessage.getTitleString())
@@ -90,7 +118,20 @@
Model.Update error = new Model.Update(
new CrossProfileQuietModeException(mUserId),
/* isRemoteActionsEnabled= */ true);
+ if (SdkLevel.isAtLeastT()) {
+ String title = mContext.getString(R.string.quiet_mode_error_title);
+ String text = mContext.getString(R.string.quiet_mode_button);
+ DevicePolicyResourcesManager devicePolicyResourcesManager = mock(
+ DevicePolicyResourcesManager.class);
+ when(mDevicePolicyManager.getResources()).thenReturn(devicePolicyResourcesManager);
+ when(devicePolicyResourcesManager.getString(eq(WORK_PROFILE_OFF_ERROR_TITLE), any()))
+ .thenReturn(title);
+ when(devicePolicyResourcesManager.getString(eq(WORK_PROFILE_OFF_ENABLE_BUTTON), any()))
+ .thenReturn(text);
+ }
+
mInflateMessage.update(error);
+
assertThat(mInflateMessage.getLayout())
.isEqualTo(InflateMessageDocumentHolder.LAYOUT_CROSS_PROFILE_ERROR);
assertThat(mInflateMessage.getTitleString())
diff --git a/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java b/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java
index 52d3c90..9a7bad5 100644
--- a/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java
+++ b/tests/unit/com/android/documentsui/inspector/InspectorControllerTest.java
@@ -280,7 +280,7 @@
assertNotNull(geoIntent);
Uri uri = geoIntent.getData();
assertEquals("geo", uri.getScheme());
- String strUri = uri.toSafeString();
+ String strUri = uri.toString();
assertTrue(strUri.contains("33."));
assertTrue(strUri.contains("-118."));
assertTrue(strUri.contains(TestEnv.FILE_JPG.displayName));
diff --git a/tests/unit/com/android/documentsui/sidebar/RootsFragmentTest.java b/tests/unit/com/android/documentsui/sidebar/RootsFragmentTest.java
index 6aaf971..ea88cfb 100644
--- a/tests/unit/com/android/documentsui/sidebar/RootsFragmentTest.java
+++ b/tests/unit/com/android/documentsui/sidebar/RootsFragmentTest.java
@@ -19,7 +19,11 @@
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
import android.content.pm.ResolveInfo;
import androidx.test.filters.MediumTest;
@@ -47,6 +51,8 @@
@MediumTest
public class RootsFragmentTest {
+ private Context mContext;
+ private DevicePolicyManager mDevicePolicyManager;
private RootsFragment mRootsFragment;
private static final String[] EXPECTED_SORTED_RESULT = {
@@ -65,13 +71,20 @@
@Before
public void setUp() {
+ mContext = mock(Context.class);
+ mDevicePolicyManager = mock(DevicePolicyManager.class);
+ when(mContext.getResources()).thenReturn(
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getResources());
+ when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
+ .thenReturn(mDevicePolicyManager);
+
mRootsFragment = new RootsFragment();
}
@Test
public void testSortLoadResult_WithCorrectOrder() {
List<Item> items = mRootsFragment.sortLoadResult(
- InstrumentationRegistry.getInstrumentation().getTargetContext().getResources(),
+ mContext,
new State(),
createFakeRootInfoList(),
null /* excludePackage */, null /* handlerAppIntent */, new TestProvidersAccess(),
diff --git a/tests/unit/com/android/documentsui/sidebar/UserItemsCombinerTest.java b/tests/unit/com/android/documentsui/sidebar/UserItemsCombinerTest.java
index 6caf236..2a80867 100644
--- a/tests/unit/com/android/documentsui/sidebar/UserItemsCombinerTest.java
+++ b/tests/unit/com/android/documentsui/sidebar/UserItemsCombinerTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.admin.DevicePolicyManager;
import android.content.res.Resources;
import android.view.View;
@@ -69,6 +70,9 @@
private final State mState = new State();
private final Resources mResources =
InstrumentationRegistry.getInstrumentation().getTargetContext().getResources();
+ private final DevicePolicyManager mDpm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getSystemService(
+ DevicePolicyManager.class);
private UserItemsCombiner mCombiner;
@Before
@@ -79,7 +83,7 @@
@Test
public void testCreatePresentableList_empty() {
- mCombiner = new UserItemsCombiner(mResources, mState)
+ mCombiner = new UserItemsCombiner(mResources, mDpm, mState)
.setRootListForCurrentUser(Collections.emptyList())
.setRootListForOtherUser(Collections.emptyList());
assertThat(mCombiner.createPresentableList()).isEmpty();
@@ -87,7 +91,7 @@
@Test
public void testCreatePresentableList_currentIsPersonal_personalItemsOnly() {
- mCombiner = new UserItemsCombiner(mResources, mState)
+ mCombiner = new UserItemsCombiner(mResources, mDpm, mState)
.setRootListForCurrentUser(PERSONAL_ITEMS)
.setRootListForOtherUser(Collections.emptyList());
assertThat(mCombiner.createPresentableList())
@@ -98,7 +102,7 @@
@Test
public void testCreatePresentableList_currentIsWork_personalItemsOnly() {
- mCombiner = new UserItemsCombiner(mResources, mState)
+ mCombiner = new UserItemsCombiner(mResources, mDpm, mState)
.overrideCurrentUserForTest(WORK_USER)
.setRootListForCurrentUser(Collections.emptyList())
.setRootListForOtherUser(PERSONAL_ITEMS);
@@ -110,7 +114,7 @@
@Test
public void testCreatePresentableList_currentIsPersonal_workItemsOnly() {
- mCombiner = new UserItemsCombiner(mResources, mState)
+ mCombiner = new UserItemsCombiner(mResources, mDpm, mState)
.setRootListForCurrentUser(Collections.emptyList())
.setRootListForOtherUser(WORK_ITEMS);
assertThat(mCombiner.createPresentableList())
@@ -121,7 +125,7 @@
@Test
public void testCreatePresentableList_currentIsWork_workItemsOnly() {
- mCombiner = new UserItemsCombiner(mResources, mState)
+ mCombiner = new UserItemsCombiner(mResources, mDpm, mState)
.overrideCurrentUserForTest(WORK_USER)
.setRootListForCurrentUser(WORK_ITEMS)
.setRootListForOtherUser(Collections.emptyList());
@@ -133,7 +137,7 @@
@Test
public void testCreatePresentableList_currentIsPersonal_personalAndWorkItems() {
- mCombiner = new UserItemsCombiner(mResources, mState)
+ mCombiner = new UserItemsCombiner(mResources, mDpm, mState)
.setRootListForCurrentUser(PERSONAL_ITEMS)
.setRootListForOtherUser(WORK_ITEMS);
@@ -151,7 +155,7 @@
@Test
public void testCreatePresentableList_currentIsWork_personalAndWorkItems() {
- mCombiner = new UserItemsCombiner(mResources, mState)
+ mCombiner = new UserItemsCombiner(mResources, mDpm, mState)
.overrideCurrentUserForTest(WORK_USER)
.setRootListForCurrentUser(WORK_ITEMS)
.setRootListForOtherUser(PERSONAL_ITEMS);
@@ -171,7 +175,7 @@
@Test
public void testCreatePresentableList_currentIsPersonal_personalAndWorkItems_cannotShare() {
mState.canShareAcrossProfile = false;
- mCombiner = new UserItemsCombiner(mResources, mState)
+ mCombiner = new UserItemsCombiner(mResources, mDpm, mState)
.setRootListForCurrentUser(PERSONAL_ITEMS)
.setRootListForOtherUser(WORK_ITEMS);
@@ -184,7 +188,7 @@
@Test
public void testCreatePresentableList_currentIsWork_personalItemsOnly_cannotShare() {
mState.canShareAcrossProfile = false;
- mCombiner = new UserItemsCombiner(mResources, mState)
+ mCombiner = new UserItemsCombiner(mResources, mDpm, mState)
.overrideCurrentUserForTest(WORK_USER)
.setRootListForCurrentUser(Collections.emptyList())
.setRootListForOtherUser(PERSONAL_ITEMS);