Prepare "grant permissions" for Tv-specific view handler.

Also, this cleans up some unused code in GrantPermissionsActivity
and fixes a latent bug in GrantPermissionsActivity#updateDefaultResults
where if the calling package was null, we were defaulting to GRANTED.

Note that we can't simply create a tv-specific layout xml file,
because the view handler is tied to the layout xml, so this change
allows for the creation of different view handlers.

b/20476102

Change-Id: Ia62051a0895e4bd314d18ba3001871b29de21ae5
diff --git a/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
index eb3c8ed..fca3d13 100644
--- a/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
@@ -16,6 +16,11 @@
 
 package com.android.packageinstaller.permission.ui;
 
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
+
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
@@ -31,7 +36,6 @@
 import android.text.style.ForegroundColorSpan;
 import android.util.ArrayMap;
 import android.util.Log;
-import android.util.SparseArray;
 
 import com.android.packageinstaller.R;
 import com.android.packageinstaller.permission.model.AppPermissionGroup;
@@ -42,22 +46,17 @@
 import java.util.ArrayList;
 import java.util.List;
 
-public class GrantPermissionsActivity extends Activity implements
-        GrantPermissionViewHandler.OnRequestGrantPermissionGroupResult {
-    private static final String LOG_TAG = "GrantPermissionsActivity";
+public class GrantPermissionsActivity extends Activity
+        implements GrantPermissionsViewHandler.ResultListener {
 
-    private static final int PERMISSION_GRANTED = 1;
-    private static final int PERMISSION_DENIED = 2;
-    private static final int PERMISSION_DENIED_RUNTIME = 3;
+    private static final String LOG_TAG = "GrantPermissionsActivity";
 
     private String[] mRequestedPermissions;
     private int[] mGrantResults;
-    private final SparseArray<String> mRequestedRuntimePermissions = new SparseArray<>();
 
     private ArrayMap<String, GroupState> mRequestGrantPermissionGroups = new ArrayMap<>();
 
-    private final GrantPermissionViewHandler mViewHandler =
-            new GrantPermissionViewHandler(this, this);
+    private GrantPermissionsViewHandler mViewHandler;
     private AppPermissions mAppPermissions;
 
     @Override
@@ -65,15 +64,23 @@
         super.onCreate(icicle);
         setFinishOnTouchOutside(false);
 
+        int uiMode = getResources().getConfiguration().uiMode & UI_MODE_TYPE_MASK;
+        if (uiMode == UI_MODE_TYPE_TELEVISION) {
+            // TODO(tvolkert): Create GrantPermissionsTvViewHandler
+            mViewHandler = new GrantPermissionsDefaultViewHandler(this).setResultListener(this);
+        } else {
+            mViewHandler = new GrantPermissionsDefaultViewHandler(this).setResultListener(this);
+        }
+
         mRequestedPermissions = getIntent().getStringArrayExtra(
                 PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES);
         if (mRequestedPermissions == null) {
             mRequestedPermissions = new String[0];
         }
 
-        mGrantResults = new int[mRequestedPermissions.length];
-
         final int requestedPermCount = mRequestedPermissions.length;
+        mGrantResults = new int[requestedPermCount];
+
         if (requestedPermCount == 0) {
             setResultAndFinish();
             return;
@@ -116,14 +123,13 @@
                     } break;
 
                     default: {
-                        mRequestGrantPermissionGroups.put(
-                                group.getName(), new GroupState(group));
+                        mRequestGrantPermissionGroups.put(group.getName(), new GroupState(group));
                     } break;
                 }
             }
         }
 
-        setContentView(mViewHandler.creatView());
+        setContentView(mViewHandler.createView());
 
         if (!showNextPermissionGroupGrantRequest()) {
             setResultAndFinish();
@@ -133,13 +139,13 @@
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        mViewHandler.onSaveInstanceState(outState);
+        mViewHandler.saveInstanceState(outState);
     }
 
     @Override
     protected void onRestoreInstanceState(Bundle savedInstanceState) {
         super.onRestoreInstanceState(savedInstanceState);
-        mViewHandler.loadSavedInstance(savedInstanceState);
+        mViewHandler.loadInstanceState(savedInstanceState);
     }
 
     private boolean showNextPermissionGroupGrantRequest() {
@@ -172,7 +178,7 @@
                 }
                 int icon = groupState.mGroup.getIconResId();
 
-                mViewHandler.showPermission(groupState.mGroup.getName(), groupCount, i,
+                mViewHandler.updateUi(groupState.mGroup.getName(), groupCount, i,
                         Icon.createWithResource(resources, icon), message,
                         groupState.mGroup.isUserSet());
                 return  true;
@@ -183,8 +189,7 @@
     }
 
     @Override
-    public void onRequestGrantPermissionGroupResult(String name, boolean granted,
-            boolean doNotAskAgain) {
+    public void onPermissionGrantResult(String name, boolean granted, boolean doNotAskAgain) {
         GroupState groupState = mRequestGrantPermissionGroups.get(name);
         if (groupState.mGroup != null) {
             if (granted) {
@@ -246,13 +251,8 @@
             case DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT: {
                 return PERMISSION_GRANTED;
             }
-
-            case DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY: {
-                return PERMISSION_DENIED;
-            }
-
             default: {
-                return PERMISSION_DENIED_RUNTIME;
+                return PERMISSION_DENIED;
             }
         }
     }
@@ -262,7 +262,7 @@
             return getPackageManager().getPackageInfo(getCallingPackage(),
                     PackageManager.GET_PERMISSIONS);
         } catch (NameNotFoundException e) {
-            Log.i(LOG_TAG, "No package:" + getCallingPackage(), e);
+            Log.i(LOG_TAG, "No package: " + getCallingPackage(), e);
             return null;
         }
     }
@@ -271,24 +271,9 @@
         final int requestedPermCount = mRequestedPermissions.length;
         for (int i = 0; i < requestedPermCount; i++) {
             String permission = mRequestedPermissions[i];
-            final int state = callingPackageInfo != null
-                    ? computePermissionGrantState(callingPackageInfo, permission,
-                            permissionPolicy)
-                    : PackageManager.PERMISSION_DENIED;
-            switch (state) {
-                case PERMISSION_GRANTED: {
-                    mGrantResults[i] = PackageManager.PERMISSION_GRANTED;
-                } break;
-
-                case PERMISSION_DENIED: {
-                    mGrantResults[i] = PackageManager.PERMISSION_DENIED;
-                } break;
-
-                case PERMISSION_DENIED_RUNTIME: {
-                    mGrantResults[i] = PackageManager.PERMISSION_DENIED;
-                    mRequestedRuntimePermissions.put(i, permission);
-                } break;
-            }
+            mGrantResults[i] = callingPackageInfo != null
+                    ? computePermissionGrantState(callingPackageInfo, permission, permissionPolicy)
+                    : PERMISSION_DENIED;
         }
     }
 
@@ -316,14 +301,14 @@
     }
 
     private static final class GroupState {
-        public static final int STATE_UNKNOWN = 0;
-        public static final int STATE_ALLOWED = 1;
-        public static final int STATE_DENIED = 2;
+        static final int STATE_UNKNOWN = 0;
+        static final int STATE_ALLOWED = 1;
+        static final int STATE_DENIED = 2;
 
-        public final AppPermissionGroup mGroup;
-        public int mState = STATE_UNKNOWN;
+        final AppPermissionGroup mGroup;
+        int mState = STATE_UNKNOWN;
 
-        public GroupState(AppPermissionGroup group) {
+        GroupState(AppPermissionGroup group) {
             mGroup = group;
         }
     }
diff --git a/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java b/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java
similarity index 91%
rename from PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java
rename to PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java
index 323396c..0d8bd6c 100644
--- a/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java
+++ b/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java
@@ -37,7 +37,8 @@
 
 import com.android.packageinstaller.R;
 
-public final class GrantPermissionViewHandler implements OnClickListener {
+final class GrantPermissionsDefaultViewHandler
+        implements GrantPermissionsViewHandler, OnClickListener {
 
     public static final String ARG_GROUP_NAME = "ARG_GROUP_NAME";
     public static final String ARG_GROUP_COUNT = "ARG_GROUP_COUNT";
@@ -56,9 +57,10 @@
     private static final long TRANSLATE_LENGTH = 317;
     private static final long GROUP_UPDATE_DELAY = 400;
 
-    private final OnRequestGrantPermissionGroupResult mResultListener;
     private final Context mContext;
 
+    private ResultListener mResultListener;
+
     private String mGroupName;
     private int mGroupCount;
     private int mGroupIndex;
@@ -90,18 +92,18 @@
         }
     };
 
-    public interface OnRequestGrantPermissionGroupResult {
-        public void onRequestGrantPermissionGroupResult(String name, boolean granted,
-                boolean doNotAskAgain);
-    }
-
-    public GrantPermissionViewHandler(OnRequestGrantPermissionGroupResult resultListener,
-            Context context) {
-        mResultListener = resultListener;
+    GrantPermissionsDefaultViewHandler(Context context) {
         mContext = context;
     }
 
-    public void onSaveInstanceState(Bundle arguments) {
+    @Override
+    public GrantPermissionsDefaultViewHandler setResultListener(ResultListener listener) {
+        mResultListener = listener;
+        return this;
+    }
+
+    @Override
+    public void saveInstanceState(Bundle arguments) {
         arguments.putString(ARG_GROUP_NAME, mGroupName);
         arguments.putInt(ARG_GROUP_COUNT, mGroupCount);
         arguments.putInt(ARG_GROUP_INDEX, mGroupIndex);
@@ -111,7 +113,8 @@
         arguments.putBoolean(ARG_GROUP_DO_NOT_ASK_CHECKED, mDoNotAskCheckbox.isChecked());
     }
 
-    public void loadSavedInstance(Bundle savedInstanceState) {
+    @Override
+    public void loadInstanceState(Bundle savedInstanceState) {
         mGroupName = savedInstanceState.getString(ARG_GROUP_NAME);
         mGroupMessage = savedInstanceState.getCharSequence(ARG_GROUP_MESSAGE);
         mGroupIcon = savedInstanceState.getParcelable(ARG_GROUP_ICON);
@@ -121,7 +124,8 @@
         mDoNotAskChecked = savedInstanceState.getBoolean(ARG_GROUP_DO_NOT_ASK_CHECKED);
     }
 
-    public void showPermission(String groupName, int groupCount, int groupIndex, Icon icon,
+    @Override
+    public void updateUi(String groupName, int groupCount, int groupIndex, Icon icon,
             CharSequence message, boolean showDonNotAsk) {
         mGroupName = groupName;
         mGroupCount = groupCount;
@@ -252,7 +256,8 @@
         mRootViewHeightController.animateAddHeight(heightDiff);
     }
 
-    public View creatView() {
+    @Override
+    public View createView() {
         mRootView = (ManualLayoutFrame) LayoutInflater.from(mContext)
                 .inflate(R.layout.grant_permissions, null);
 
@@ -266,9 +271,9 @@
         mDescContainer = (ViewGroup) mRootView.findViewById(R.id.desc_container);
         mCurrentDesc = (ViewGroup) mRootView.findViewById(R.id.perm_desc_root);
 
-        mRootView.findViewById(R.id.permission_allow_button).setOnClickListener(this);
+        mAllowButton.setOnClickListener(this);
         mRootView.findViewById(R.id.permission_deny_button).setOnClickListener(this);
-        mRootView.findViewById(R.id.do_not_ask_checkbox).setOnClickListener(this);
+        mDoNotAskCheckbox.setOnClickListener(this);
 
         if (mGroupName != null) {
             updateDescription();
@@ -309,12 +314,16 @@
     public void onClick(View view) {
         switch (view.getId()) {
             case R.id.permission_allow_button:
-                mResultListener.onRequestGrantPermissionGroupResult(mGroupName, true, false);
+                if (mResultListener != null) {
+                    mResultListener.onPermissionGrantResult(mGroupName, true, false);
+                }
                 break;
             case R.id.permission_deny_button:
                 mAllowButton.setEnabled(true);
-                mResultListener.onRequestGrantPermissionGroupResult(mGroupName, false,
-                        mDoNotAskCheckbox.isChecked());
+                if (mResultListener != null) {
+                    mResultListener.onPermissionGrantResult(mGroupName, false,
+                            mDoNotAskCheckbox.isChecked());
+                }
                 break;
             case R.id.do_not_ask_checkbox:
                 mAllowButton.setEnabled(!mDoNotAskCheckbox.isChecked());
@@ -326,7 +335,7 @@
      * Manually controls the height of a view through getBottom/setTop.  Also listens
      * for layout changes and sets the height again to be sure it doesn't change.
      */
-    public static final class ViewHeightController implements OnLayoutChangeListener {
+    private static final class ViewHeightController implements OnLayoutChangeListener {
         private final View mView;
         private int mHeight;
 
diff --git a/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java b/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java
new file mode 100644
index 0000000..36ba4e4
--- /dev/null
+++ b/PermissionController/src/com/android/packageinstaller/permission/ui/GrantPermissionsViewHandler.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+package com.android.packageinstaller.permission.ui;
+
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.view.View;
+
+/**
+ * Class for managing the presentation and user interaction of the "grant
+ * permissions" user interface.
+ */
+interface GrantPermissionsViewHandler {
+
+    /**
+     * Listener interface for getting notified when the user responds to a
+     * permissions grant request.
+     */
+    interface ResultListener {
+        void onPermissionGrantResult(String groupName, boolean granted, boolean doNotAskAgain);
+    }
+
+    /**
+     * Creates and returns the view hierarchy that is managed by this view
+     * handler. This must be called before {@link #updateUi}.
+     */
+    View createView();
+
+    /**
+     * Updates the view hierarchy to reflect the specified state.
+     * <p>
+     * Note that this must be called at least once before showing the UI to
+     * the user to properly initialize the UI.
+     *
+     * @param groupName the name of the permission group
+     * @param groupCount the total number of groups that are being requested
+     * @param groupIndex the index of the current group being requested
+     * @param icon the icon representation of the current group
+     * @param message the message to display the user
+     * @param showDoNotAsk whether to show the "do not ask again" option
+     */
+    void updateUi(String groupName, int groupCount, int groupIndex, Icon icon,
+            CharSequence message, boolean showDoNotAsk);
+
+    /**
+     * Sets the result listener that will be notified when the user responds
+     * to a permissions grant request.
+     */
+    GrantPermissionsViewHandler setResultListener(ResultListener listener);
+
+    /**
+     * Called by {@link GrantPermissionsActivity} to save the state of this
+     * view handler to the specified bundle.
+     */
+    void saveInstanceState(Bundle outState);
+
+    /**
+     * Called by {@link GrantPermissionsActivity} to load the state of this
+     * view handler from the specified bundle.
+     */
+    void loadInstanceState(Bundle savedInstanceState);
+}