Fix loading screens for manage and running apps

Also add loading screen to manage permissions as this can take a
long time to load in some circumstances. Build loading screens into
Utils and SettingsPreferenceFragment so that it can be easily used
other places in the future.

Change-Id: I7febd06695487e02ced793a9fd418051b5f0eab8
diff --git a/res/layout/loading_container.xml b/res/layout/loading_container.xml
new file mode 100644
index 0000000..eb67044
--- /dev/null
+++ b/res/layout/loading_container.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/loading_container"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:visibility="gone"
+    android:gravity="center">
+
+    <ProgressBar style="?android:attr/progressBarStyleLarge"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <TextView android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:text="@string/settings_safetylegal_activity_loading"
+        android:paddingTop="4dip"
+        android:singleLine="true" />
+
+</LinearLayout>
diff --git a/res/layout/manage_applications_apps.xml b/res/layout/manage_applications_apps.xml
index 1e0518d..044cdb4 100644
--- a/res/layout/manage_applications_apps.xml
+++ b/res/layout/manage_applications_apps.xml
@@ -52,25 +52,7 @@
 
         </LinearLayout>
 
-        <LinearLayout android:id="@+id/loading_container"
-                android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:visibility="gone"
-                android:gravity="center">
-
-            <ProgressBar style="?android:attr/progressBarStyleLarge"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content" />
-
-            <TextView android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:text="@string/settings_safetylegal_activity_loading"
-                    android:paddingTop="4dip"
-                    android:singleLine="true" />
-
-        </LinearLayout>
+        <include layout="@layout/loading_container" />
 
     </FrameLayout>
 
diff --git a/res/layout/manage_applications_running.xml b/res/layout/manage_applications_running.xml
index 485523a..6a9d4e5 100644
--- a/res/layout/manage_applications_running.xml
+++ b/res/layout/manage_applications_running.xml
@@ -29,25 +29,7 @@
                 android:layout_height="match_parent"
                 android:visibility="gone" />
 
-        <LinearLayout android:id="@+id/loading_container"
-                android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:visibility="gone"
-                android:gravity="center">
-
-            <ProgressBar style="?android:attr/progressBarStyleLarge"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content" />
-
-            <TextView android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:text="@string/settings_safetylegal_activity_loading"
-                    android:paddingTop="4dip"
-                    android:singleLine="true" />
-
-        </LinearLayout>
+        <include layout="@layout/loading_container" />
 
     </FrameLayout>
 
diff --git a/res/layout/preference_list_fragment.xml b/res/layout/preference_list_fragment.xml
index b47e175..6e8ad91 100644
--- a/res/layout/preference_list_fragment.xml
+++ b/res/layout/preference_list_fragment.xml
@@ -29,20 +29,27 @@
                  android:layout_height="wrap_content"
                  android:visibility="gone" />
 
-    <ListView android:id="@android:id/list"
-              style="@style/PreferenceFragmentListSinglePane"
-              android:layout_width="match_parent"
-              android:layout_height="0px"
-              android:layout_weight="1"
-              android:paddingStart="@dimen/settings_side_margin"
-              android:paddingEnd="@dimen/settings_side_margin"
-              android:paddingTop="@dimen/dashboard_padding_top"
-              android:paddingBottom="@dimen/dashboard_padding_bottom"
-              android:scrollbarStyle="@*android:integer/preference_fragment_scrollbarStyle"
-              android:clipToPadding="false"
-              android:drawSelectorOnTop="false"
-              android:elevation="@dimen/dashboard_category_elevation"
-              android:scrollbarAlwaysDrawVerticalTrack="true" />
+    <FrameLayout android:layout_height="0px"
+                 android:layout_weight="1"
+                 android:layout_width="match_parent">
+
+        <ListView android:id="@android:id/list"
+                  style="@style/PreferenceFragmentListSinglePane"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:paddingStart="@dimen/settings_side_margin"
+                  android:paddingEnd="@dimen/settings_side_margin"
+                  android:paddingTop="@dimen/dashboard_padding_top"
+                  android:paddingBottom="@dimen/dashboard_padding_bottom"
+                  android:scrollbarStyle="@*android:integer/preference_fragment_scrollbarStyle"
+                  android:clipToPadding="false"
+                  android:drawSelectorOnTop="false"
+                  android:elevation="@dimen/dashboard_category_elevation"
+                  android:scrollbarAlwaysDrawVerticalTrack="true" />
+
+        <include layout="@layout/loading_container" />
+
+    </FrameLayout>
 
     <TextView android:id="@android:id/empty"
               android:layout_width="match_parent"
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index bf41c80..130e29d 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -158,6 +158,11 @@
         unregisterObserverIfNeeded();
     }
 
+    public void showLoadingWhenEmpty() {
+        View loading = getView().findViewById(R.id.loading_container);
+        getListView().setEmptyView(loading);
+    }
+
     public void registerObserverIfNeeded() {
         if (!mIsDataSetObserverRegistered) {
             if (mCurrentRootAdapter != null) {
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 23b2c85..dc4b484 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -39,8 +39,8 @@
 import android.content.pm.Signature;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.content.res.Resources.NotFoundException;
+import android.content.res.TypedArray;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -74,6 +74,9 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
 import android.widget.ListView;
 import android.widget.TabWidget;
 
@@ -1158,4 +1161,39 @@
                 ? R.string.launch_defaults_some
                 : R.string.launch_defaults_none);
     }
+
+    public static void handleLoadingContainer(View loading, View doneLoading, boolean done,
+            boolean animate) {
+        setViewShown(loading, !done, animate);
+        setViewShown(doneLoading, done, animate);
+    }
+
+    private static void setViewShown(final View view, boolean shown, boolean animate) {
+        if (animate) {
+            Animation animation = AnimationUtils.loadAnimation(view.getContext(),
+                    shown ? android.R.anim.fade_in : android.R.anim.fade_out);
+            if (shown) {
+                view.setVisibility(View.VISIBLE);
+            } else {
+                animation.setAnimationListener(new AnimationListener() {
+                    @Override
+                    public void onAnimationStart(Animation animation) {
+                    }
+
+                    @Override
+                    public void onAnimationRepeat(Animation animation) {
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Animation animation) {
+                        view.setVisibility(View.INVISIBLE);
+                    }
+                });
+            }
+            view.startAnimation(animation);
+        } else {
+            view.clearAnimation();
+            view.setVisibility(shown ? View.VISIBLE : View.INVISIBLE);
+        }
+    }
 }
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index b0b35ab..4acbedb 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -358,6 +358,7 @@
         updateOptionsMenu();
         if (mApplications != null) {
             mApplications.resume(mSortOrder);
+            mApplications.updateLoading();
         }
     }
 
@@ -746,17 +747,20 @@
             }
             notifyDataSetChanged();
 
-            if (entries == null) {
-                mManageApplications.mListContainer.setVisibility(View.INVISIBLE);
-                mManageApplications.mLoadingContainer.setVisibility(View.VISIBLE);
-            } else {
-                mManageApplications.mListContainer.setVisibility(View.VISIBLE);
-                mManageApplications.mLoadingContainer.setVisibility(View.GONE);
+            if (mEntries.size() != 0
+                    && mManageApplications.mListContainer.getVisibility() != View.VISIBLE) {
+                Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
+                        mManageApplications.mListContainer, true, true);
             }
 
             mManageApplications.setHasDisabled(hasDisabledApps());
         }
 
+        private void updateLoading() {
+            Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
+                    mManageApplications.mListContainer, mEntries.size() != 0, false);
+        }
+
         private boolean hasDisabledApps() {
             ArrayList<AppEntry> allApps = mSession.getAllApps();
             for (int i = 0; i < allApps.size(); i++) {
diff --git a/src/com/android/settings/applications/ManagePermissions.java b/src/com/android/settings/applications/ManagePermissions.java
index 8fb3e62..a6d29c5 100644
--- a/src/com/android/settings/applications/ManagePermissions.java
+++ b/src/com/android/settings/applications/ManagePermissions.java
@@ -36,7 +36,6 @@
 
     private static final String TAG = "ManagePermissions";
 
-    private boolean mLoadComplete;
     private PermissionsInfo mPermissionsInfo;
 
     @Override
@@ -46,6 +45,13 @@
         mPermissionsInfo = new PermissionsInfo(getActivity(), this);
     }
 
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        showLoadingWhenEmpty();
+    }
+
     private void refreshUi() {
         PreferenceScreen screen = getPreferenceScreen();
         if (screen == null) {
diff --git a/src/com/android/settings/applications/RunningServices.java b/src/com/android/settings/applications/RunningServices.java
index a4cd4a7..1841f13 100644
--- a/src/com/android/settings/applications/RunningServices.java
+++ b/src/com/android/settings/applications/RunningServices.java
@@ -23,9 +23,9 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.animation.AnimationUtils;
 
 import com.android.settings.R;
+import com.android.settings.Utils;
 
 public class RunningServices extends Fragment {
 
@@ -69,12 +69,7 @@
     public void onResume() {
         super.onResume();
         boolean haveData = mRunningProcessesView.doResume(this, mRunningProcessesAvail);
-        if (haveData) {
-            mRunningProcessesView.setVisibility(View.VISIBLE);
-            mLoadingContainer.setVisibility(View.INVISIBLE);
-        } else {
-            mLoadingContainer.setVisibility(View.VISIBLE);
-        }
+        Utils.handleLoadingContainer(mLoadingContainer, mRunningProcessesView, haveData, false);
     }
 
     @Override
@@ -110,19 +105,10 @@
         mOptionsMenu.findItem(SHOW_BACKGROUND_PROCESSES).setVisible(!showingBackground);
     }
 
-    private void handleRunningProcessesAvail() {
-        mLoadingContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(),
-                android.R.anim.fade_out));
-        mRunningProcessesView.startAnimation(AnimationUtils.loadAnimation(getActivity(),
-                android.R.anim.fade_in));
-        mRunningProcessesView.setVisibility(View.VISIBLE);
-        mLoadingContainer.setVisibility(View.GONE);
-    }
-
     private final Runnable mRunningProcessesAvail = new Runnable() {
         @Override
         public void run() {
-            handleRunningProcessesAvail();
+            Utils.handleLoadingContainer(mLoadingContainer, mRunningProcessesView, true, true);
         }
     };