Merge "Configuration of workspace through app restrictions"
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index a5d2228..3f7322c 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -77,6 +77,28 @@
                 TAG_WORKSPACE);
     }
 
+    static AutoInstallsLayout get(String packageName, int xmlResourceId, Context context,
+            AppWidgetHost appWidgetHost, LayoutParserCallback callback) {
+
+        Resources resources;
+        try {
+            resources = context.getPackageManager().getResourcesForApplication(packageName);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "Package not found: " + packageName);
+            return null;
+        }
+
+        // Verify that the XML resource exists
+        String resourceName = resources.getResourceName(xmlResourceId);
+        if (resourceName == null || !resourceName.startsWith(packageName)) {
+            Log.e(TAG, "Cannot find resource id:" + xmlResourceId + " in package " + packageName);
+            return null;
+        }
+
+        return new AutoInstallsLayout(context, appWidgetHost, callback, resources, xmlResourceId,
+                TAG_WORKSPACE);
+    }
+
     // Object Tags
     private static final String TAG_WORKSPACE = "workspace";
     private static final String TAG_APP_ICON = "appicon";
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 1715b02..58533c9 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3;
 
+import android.annotation.TargetApi;
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
@@ -40,6 +41,9 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
@@ -79,6 +83,9 @@
 
     private static final String URI_PARAM_IS_EXTERNAL_ADD = "isExternalAdd";
 
+    private static final String RESTRICTION_PACKAGE_NAME = "workspace.configuration.package.name";
+    private static final String RESTRICTION_XML_RES_ID = "workspace.configuration.xml.resource.id";
+
     private LauncherProviderChangeListener mListener;
 
     /**
@@ -301,9 +308,10 @@
 
     /**
      * Loads the default workspace based on the following priority scheme:
-     *   1) From a package provided by play store
-     *   2) From a partner configuration APK, already in the system image
-     *   3) The default configuration for the particular device
+     *   1) From the app restrictions
+     *   2) From a package provided by play store
+     *   3) From a partner configuration APK, already in the system image
+     *   4) The default configuration for the particular device
      */
     synchronized public void loadDefaultFavoritesIfNecessary() {
         String spKey = LauncherAppState.getSharedPreferencesKey();
@@ -312,9 +320,16 @@
         if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
             Log.d(TAG, "loading default workspace");
 
-            AutoInstallsLayout loader = AutoInstallsLayout.get(getContext(),
-                    mOpenHelper.mAppWidgetHost, mOpenHelper);
+            // Application restrictions
+            AutoInstallsLayout loader = createWorkspaceLoaderFromAppRestriction();
 
+            // Play Store
+            if (loader == null) {
+                loader = AutoInstallsLayout.get(getContext(), mOpenHelper.mAppWidgetHost,
+                        mOpenHelper);
+            }
+
+            // Partner APK
             if (loader == null) {
                 final Partner partner = Partner.get(getContext().getPackageManager());
                 if (partner != null && partner.hasDefaultLayout()) {
@@ -329,6 +344,7 @@
             }
 
             final boolean usingExternallyProvidedLayout = loader != null;
+            // Default configuration
             if (loader == null) {
                 loader = getDefaultLayoutParser();
             }
@@ -344,6 +360,39 @@
         }
     }
 
+    /**
+     * Creates workspace loader from an XML resource listed in the app restrictions.
+     *
+     * @return the loader if the restrictions are set and the resource exists; null otherwise.
+     */
+    @TargetApi(18)
+    private AutoInstallsLayout createWorkspaceLoaderFromAppRestriction() {
+
+        // UserManager.getApplicationRestrictions() requires minSdkVersion >= 18
+        if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
+            return null;
+        }
+
+        Context ctx = getContext();
+        UserManager um = (UserManager) ctx.getSystemService(Context.USER_SERVICE);
+        Bundle bundle = um.getApplicationRestrictions(ctx.getPackageName());
+        String packageName = bundle.getString(RESTRICTION_PACKAGE_NAME);
+        int xmlResourceId = bundle.getInt(RESTRICTION_XML_RES_ID);
+
+        AutoInstallsLayout loader = null;
+        if (packageName != null && xmlResourceId != 0) {
+            loader = AutoInstallsLayout.get(packageName, xmlResourceId, getContext(),
+                    mOpenHelper.mAppWidgetHost, mOpenHelper);
+
+        }
+
+        if (loader != null) {
+            Log.d(TAG, "Will load workspace configuration from " + packageName);
+        }
+
+        return loader;
+    }
+
     private DefaultLayoutParser getDefaultLayoutParser() {
         int defaultLayout = LauncherAppState.getInstance()
                 .getDynamicGrid().getDeviceProfile().defaultLayoutId;