Merge "[Panlingual] Avoid activity restart during rotation" into tm-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 15c5272..4117b2e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1452,7 +1452,8 @@
         <activity
             android:name=".datausage.AppDataUsageActivity"
             android:exported="true"
-            android:noHistory="true">
+            android:noHistory="true"
+            android:permission="android.permission.QUERY_ALL_PACKAGES">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -1522,6 +1523,7 @@
         <activity-alias android:name=".applications.InstalledAppDetails"
                 android:label="@string/application_info_label"
                 android:exported="true"
+                android:permission="android.permission.QUERY_ALL_PACKAGES"
                 android:targetActivity=".applications.InstalledAppDetailsTop">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.APPLICATION_DETAILS_SETTINGS" />
@@ -1535,7 +1537,8 @@
 
         <activity android:name=".applications.InstalledAppOpenByDefaultActivity"
                   android:label="@string/application_info_label"
-                  android:exported="true">
+                  android:exported="true"
+                  android:permission="android.permission.QUERY_ALL_PACKAGES">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.APP_OPEN_BY_DEFAULT_SETTINGS" />
                 <!-- Also catch legacy "com." prefixed action. -->
@@ -1906,7 +1909,8 @@
         <activity
             android:name="Settings$AppUsageAccessSettingsActivity"
             android:exported="true"
-            android:label="@string/usage_access_title">
+            android:label="@string/usage_access_title"
+            android:permission="android.permission.QUERY_ALL_PACKAGES">
             <intent-filter>
                 <action android:name="android.settings.USAGE_ACCESS_SETTINGS"/>
                 <category android:name="android.intent.category.DEFAULT"/>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c80e42c..f11cee5 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -452,6 +452,7 @@
 
     <!-- Text padding for EmptyTextSettings -->
     <dimen name="empty_text_padding">24dp</dimen>
+    <dimen name="empty_text_layout_height">450dp</dimen>
 
     <!--  Choose SIM Activity dimens  -->
     <dimen name="subtitle_bottom_padding">24dp</dimen>
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 3eae885..062bfc5 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -330,8 +330,8 @@
             if (className.equals(Settings.NotificationReviewPermissionsActivity.class.getName())) {
                 // Special-case for a case where a user is directed to the all apps notification
                 // preferences page via a notification prompt to review permissions settings.
-                android.provider.Settings.Secure.putInt(getContext().getContentResolver(),
-                        android.provider.Settings.Secure.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
+                android.provider.Settings.Global.putInt(getContext().getContentResolver(),
+                        android.provider.Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE,
                         1);  // USER_INTERACTED
             }
         } else if (className.equals(AppLocaleDetails.class.getName())) {
diff --git a/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccess.java b/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccess.java
index f1c578e..3df19be 100644
--- a/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccess.java
+++ b/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccess.java
@@ -68,7 +68,7 @@
     @Override
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        setLoading(true, false);
+        setEmptyText(R.string.premium_sms_none);
     }
 
     @Override
@@ -138,8 +138,6 @@
 
     private void updatePrefs(ArrayList<AppEntry> apps) {
         if (apps == null) return;
-        setEmptyText(R.string.premium_sms_none);
-        setLoading(false, true);
         final PreferenceScreen screen = getPreferenceScreen();
         screen.removeAll();
         screen.setOrderingAsAdded(true);
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index f3085bc..b1ffcf1 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -69,7 +69,7 @@
         mCm = cm;
         mVm = vm;
         mResources = resources;
-        mWorkPolicyUtils = new WorkPolicyUtils(mContext, mPm, mUm, mDpm);
+        mWorkPolicyUtils = new WorkPolicyUtils(mContext);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
index 8fb0d1e..db4cc53 100644
--- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
@@ -424,6 +424,9 @@
 
     @VisibleForTesting
     void setUsageSummary(Preference preference, BatteryEntry entry) {
+        if (entry.getUid() == Process.SYSTEM_UID) {
+          return;
+        }
         // Only show summary when usage time is longer than one minute
         final long usageTimeMs = entry.getTimeInForegroundMs();
         if (shouldShowSummary(entry) && usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) {
diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java
index 98f19fe..b1e4c34 100644
--- a/src/com/android/settings/fuelgauge/BatteryInfo.java
+++ b/src/com/android/settings/fuelgauge/BatteryInfo.java
@@ -153,6 +153,7 @@
         new AsyncTask<Void, Void, BatteryInfo>() {
             @Override
             protected BatteryInfo doInBackground(Void... params) {
+                boolean shouldCloseBatteryUsageStats = false;
                 BatteryUsageStats stats;
                 if (batteryUsageStats != null) {
                     stats = batteryUsageStats;
@@ -160,6 +161,7 @@
                     try {
                         stats = context.getSystemService(BatteryStatsManager.class)
                                 .getBatteryUsageStats();
+                        shouldCloseBatteryUsageStats = true;
                     } catch (RuntimeException e) {
                         Log.e(TAG, "getBatteryInfo() from getBatteryUsageStats()", e);
                         // Use default BatteryUsageStats.
@@ -168,10 +170,12 @@
                 }
                 final BatteryInfo batteryInfo =
                         getBatteryInfo(context, stats, shortString);
-                try {
-                    stats.close();
-                } catch (Exception e) {
-                    Log.e(TAG, "BatteryUsageStats.close() failed", e);
+                if (shouldCloseBatteryUsageStats) {
+                    try {
+                        stats.close();
+                    } catch (Exception e) {
+                        Log.e(TAG, "BatteryUsageStats.close() failed", e);
+                    }
                 }
                 return batteryInfo;
             }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java
index e950679..6563155 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageBase.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java
@@ -83,6 +83,7 @@
     public void onStop() {
         super.onStop();
         mBatteryBroadcastReceiver.unRegister();
+        closeBatteryUsageStatsIfNeeded();
     }
 
     protected void restartBatteryStatsLoader(int refreshType) {
@@ -104,16 +105,6 @@
         final long startTime = System.currentTimeMillis();
         historyPref.setBatteryUsageStats(mBatteryUsageStats);
         BatteryUtils.logRuntime(TAG, "updatePreference", startTime);
-        if (mBatteryUsageStats == null) {
-            return;
-        }
-        try {
-            mBatteryUsageStats.close();
-        } catch (Exception e) {
-            Log.e(TAG, "BatteryUsageStats.close() failed", e);
-        } finally {
-            mBatteryUsageStats = null;
-        }
     }
 
     private class BatteryUsageStatsLoaderCallbacks
@@ -130,6 +121,7 @@
         @Override
         public void onLoadFinished(Loader<BatteryUsageStats> loader,
                 BatteryUsageStats batteryUsageStats) {
+            closeBatteryUsageStatsIfNeeded();
             mBatteryUsageStats = batteryUsageStats;
             PowerUsageBase.this.onLoadFinished(mRefreshType);
         }
@@ -138,4 +130,17 @@
         public void onLoaderReset(Loader<BatteryUsageStats> loader) {
         }
     }
+
+    private void closeBatteryUsageStatsIfNeeded() {
+        if (mBatteryUsageStats == null) {
+            return;
+        }
+        try {
+            mBatteryUsageStats.close();
+        } catch (Exception e) {
+            Log.e(TAG, "BatteryUsageStats.close() failed", e);
+        } finally {
+            mBatteryUsageStats = null;
+        }
+    }
 }
diff --git a/src/com/android/settings/localepicker/AppLocalePickerActivity.java b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
index 4700f3f..1ed6f5b 100644
--- a/src/com/android/settings/localepicker/AppLocalePickerActivity.java
+++ b/src/com/android/settings/localepicker/AppLocalePickerActivity.java
@@ -30,7 +30,6 @@
 import android.widget.FrameLayout;
 import android.widget.ListView;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.LocalePickerWithRegion;
 import com.android.internal.app.LocaleStore;
 import com.android.settings.R;
@@ -38,10 +37,6 @@
 import com.android.settings.applications.appinfo.AppLocaleDetails;
 import com.android.settings.core.SettingsBaseActivity;
 
-/**
- * TODO(b/223503670): Add unit test for AppLocalePickerActivity.
- * A activity to show the locale picker and information page.
- */
 public class AppLocalePickerActivity extends SettingsBaseActivity
         implements LocalePickerWithRegion.LocaleSelectedListener {
     private static final String TAG = AppLocalePickerActivity.class.getSimpleName();
@@ -128,8 +123,7 @@
         return appLocaleDetailsContainer;
     }
 
-    @VisibleForTesting
-    void launchLocalePickerPage() {
+    private void launchLocalePickerPage() {
         // LocalePickerWithRegion use android.app.ListFragment. Thus, it can not use
         // getSupportFragmentManager() to add this into container.
         android.app.FragmentManager fragmentManager = getFragmentManager();
diff --git a/src/com/android/settings/notification/MediaVolumePreferenceController.java b/src/com/android/settings/notification/MediaVolumePreferenceController.java
index 978a4b4..c0d5610 100644
--- a/src/com/android/settings/notification/MediaVolumePreferenceController.java
+++ b/src/com/android/settings/notification/MediaVolumePreferenceController.java
@@ -35,6 +35,7 @@
 import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.SliceBackgroundWorker;
 import com.android.settingslib.media.MediaDevice;
+import com.android.settingslib.media.MediaOutputConstants;
 
 public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceController {
     private static final String TAG = "MediaVolumePreCtrl";
@@ -106,8 +107,10 @@
 
         final Intent intent = new Intent();
         if (getWorker().isDeviceBroadcasting()) {
-            // TODO(b/229577323) : Get the intent action for the Media Output Broadcast Dialog
-            //  in SystemUI
+            intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME);
+            intent.setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
+            intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME,
+                    getWorker().getActiveLocalMediaController().getPackageName());
         } else {
             // TODO(b/229577518) : Get the intent action of the Bluetooth Broadcast Dialog
             //  for user to choose the action
diff --git a/src/com/android/settings/widget/EmptyTextSettings.java b/src/com/android/settings/widget/EmptyTextSettings.java
index 87513dd..a6e5c60 100644
--- a/src/com/android/settings/widget/EmptyTextSettings.java
+++ b/src/com/android/settings/widget/EmptyTextSettings.java
@@ -43,8 +43,10 @@
         TypedValue value = new TypedValue();
         getContext().getTheme().resolveAttribute(android.R.attr.textAppearanceMedium, value, true);
         mEmpty.setTextAppearance(value.resourceId);
+        final int layoutHeight = getContext().getResources()
+                .getDimensionPixelSize(R.dimen.empty_text_layout_height);
         ((ViewGroup) view.findViewById(android.R.id.list_container)).addView(mEmpty,
-                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+                new LayoutParams(LayoutParams.MATCH_PARENT, layoutHeight));
         setEmptyView(mEmpty);
     }
 
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
index 0005e71..87a447d 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
@@ -105,6 +105,10 @@
         when(mContext.getApplicationContext()).thenReturn(mContext);
         resetAndInitializePackageManager();
         when(mUserManager.getProfiles(mUserId)).thenReturn(mProfiles);
+        when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
+                .thenReturn(mDevicePolicyManager);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
         mProfiles.add(new UserInfo(mUserId, "", "", 0 /* flags */));
         mResources = RuntimeEnvironment.application.getResources();
 
diff --git a/tests/robotests/src/com/android/settings/localepicker/AppLocalePickerActivityTest.java b/tests/robotests/src/com/android/settings/localepicker/AppLocalePickerActivityTest.java
new file mode 100644
index 0000000..4d5e0b9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/localepicker/AppLocalePickerActivityTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.settings.localepicker;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+import android.app.ApplicationPackageManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.InstallSourceInfo;
+import android.net.Uri;
+import android.os.Process;
+import android.os.UserHandle;
+import android.telephony.TelephonyManager;
+
+import androidx.fragment.app.Fragment;
+
+import com.android.settings.R;
+import com.android.settings.applications.AppInfoBase;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowTelephonyManager;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(
+        shadows = {
+                AppLocalePickerActivityTest.ShadowApplicationPackageManager.class,
+        })
+public class AppLocalePickerActivityTest {
+    private static final String TEST_PACKAGE_NAME = "com.android.settings";
+    private static final Uri TEST_PACKAGE_URI = Uri.parse("package:" + TEST_PACKAGE_NAME);
+
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    @Test
+    public void launchAppLocalePickerActivity_hasPackageName_success() {
+        ActivityController<TestAppLocalePickerActivity> controller =
+                initActivityController(true);
+
+        controller.create();
+
+        assertThat(controller.get().isFinishing()).isFalse();
+    }
+
+    @Test
+    public void launchAppLocalePickerActivity_intentWithoutPackageName_failed() {
+        ActivityController<TestAppLocalePickerActivity> controller =
+                initActivityController(false);
+
+        controller.create();
+
+        assertThat(controller.get().isFinishing()).isTrue();
+    }
+
+    private ActivityController<TestAppLocalePickerActivity> initActivityController(
+            boolean hasPackageName) {
+        Intent data = new Intent();
+        if (hasPackageName) {
+            data.setData(TEST_PACKAGE_URI);
+        }
+        data.putExtra(AppInfoBase.ARG_PACKAGE_UID, UserHandle.getUserId(Process.myUid()));
+        ActivityController<TestAppLocalePickerActivity> activityController =
+                Robolectric.buildActivity(TestAppLocalePickerActivity.class, data);
+        Activity activity = activityController.get();
+
+        ShadowTelephonyManager shadowTelephonyManager = Shadows.shadowOf(
+                activity.getSystemService(TelephonyManager.class));
+        shadowTelephonyManager.setSimCountryIso("US");
+        shadowTelephonyManager.setNetworkCountryIso("US");
+
+        return activityController;
+    }
+
+    private static class TestAppLocalePickerActivity extends AppLocalePickerActivity {
+        @Override
+        public Context createContextAsUser(UserHandle user, int flags) {
+            // return the current context as a work profile
+            return this;
+        }
+    }
+
+    @Implements(ApplicationPackageManager.class)
+    public static class ShadowApplicationPackageManager extends
+            org.robolectric.shadows.ShadowApplicationPackageManager {
+
+        @Implementation
+        protected Object getInstallSourceInfo(String packageName) {
+            return new InstallSourceInfo("", null, null, "");
+        }
+    }
+}