summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Monk <jmonk@google.com>2015-05-06 09:58:34 -0400
committerJason Monk <jmonk@google.com>2015-05-08 09:07:58 -0400
commit2bcb3ddd1c25d422e80cde57f6db392866a07674 (patch)
tree15d4fc247c76ad73b9fc9a198afccc20061dda7f /src
parent45d0ee617557bce475fa31468aa5be909f603172 (diff)
downloadandroid_packages_apps_PackageInstaller-2bcb3ddd1c25d422e80cde57f6db392866a07674.tar.gz
android_packages_apps_PackageInstaller-2bcb3ddd1c25d422e80cde57f6db392866a07674.tar.bz2
android_packages_apps_PackageInstaller-2bcb3ddd1c25d422e80cde57f6db392866a07674.zip
Add animation for multiple permission checks
- DialogFragment was removed and just use the dialog-themed activity instead. The previously GrantPermissionFragment, now acts as a helper class. - The dialog always tells the window its the same size, but then draws at whatever height is required for the current permission. (this allows it to stay in one position) - Touching outside now does nothing so that the user must respond to the permission request. Change-Id: I12f27de4de5ad83e123cb9acfa062950db39f61b
Diffstat (limited to 'src')
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionFragment.java129
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java334
-rw-r--r--src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java56
-rw-r--r--src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java66
4 files changed, 430 insertions, 155 deletions
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionFragment.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionFragment.java
deleted file mode 100644
index 0458f9b9..00000000
--- a/src/com/android/packageinstaller/permission/ui/GrantPermissionFragment.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.app.Activity;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.packageinstaller.R;
-import com.android.packageinstaller.permission.utils.Utils;
-
-public final class GrantPermissionFragment extends DialogFragment {
- public static final String ARG_GROUP_NAME = "ARG_GROUP_NAME";
- public static final String ARG_GROUP_COUNT = "ARG_GROUP_COUNT";
- public static final String ARG_GROUP_INDEX = "ARG_GROUP_INDEX";
- public static final String ARG_GROUP_ICON_RES_ID = "ARG_GROUP_ICON";
- public static final String ARG_GROUP_ICON_PKG = "ARG_GROUP_ICON_PKG";
- public static final String ARG_GROUP_MESSAGE = "ARG_GROUP_MESSAGE";
-
- public interface OnRequestGrantPermissionGroupResult {
- public void onRequestGrantPermissionGroupResult(String name, boolean granted);
- }
-
- public static GrantPermissionFragment newInstance(String groupName, int groupCount,
- int groupIndex, String iconPkg, int iconResId, CharSequence message) {
- GrantPermissionFragment instance = new GrantPermissionFragment();
- instance.setStyle(STYLE_NORMAL,
- android.R.style.Theme_DeviceDefault_Light_Dialog_NoActionBar);
-
- Bundle arguments = new Bundle();
- arguments.putString(ARG_GROUP_NAME, groupName);
- arguments.putInt(ARG_GROUP_COUNT, groupCount);
- arguments.putInt(ARG_GROUP_INDEX, groupIndex);
- arguments.putInt(ARG_GROUP_ICON_RES_ID, iconResId);
- arguments.putString(ARG_GROUP_ICON_PKG, iconPkg);
- arguments.putCharSequence(ARG_GROUP_MESSAGE, message);
- instance.setArguments(arguments);
-
- return instance;
- }
-
- private String mGroupName;
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View content = inflater.inflate(R.layout.grant_permissions, container, false);
-
- mGroupName = getArguments().getString(ARG_GROUP_NAME);
- final CharSequence message = getArguments().getCharSequence(ARG_GROUP_MESSAGE);
- final String iconPkg = getArguments().getString(ARG_GROUP_ICON_PKG);
- final int iconResId = getArguments().getInt(ARG_GROUP_ICON_RES_ID);
- final int groupCount = getArguments().getInt(ARG_GROUP_COUNT);
- final int groupIndex = getArguments().getInt(ARG_GROUP_INDEX);
-
- final ImageView iconView = (ImageView) content.findViewById(R.id.permission_icon);
- final View allowButton = content.findViewById(R.id.permission_allow_button);
- final View denyButton = content.findViewById(R.id.permission_deny_button);
- final View doNotAskCheckbox = content.findViewById(R.id.do_not_ask_checkbox);
- final TextView currentGroupView = (TextView) content.findViewById(R.id.current_page_text);
- final TextView messageView = (TextView) content.findViewById(R.id.permission_message);
-
- OnClickListener clickListener = new OnClickListener() {
- @Override
- public void onClick(View view) {
- if (view == allowButton) {
- ((OnRequestGrantPermissionGroupResult) getActivity())
- .onRequestGrantPermissionGroupResult(mGroupName, true);
- } else if (view == denyButton) {
- ((OnRequestGrantPermissionGroupResult) getActivity())
- .onRequestGrantPermissionGroupResult(mGroupName, false);
- } else if (view == doNotAskCheckbox) {
- //TODO: Implement me.
- }
- }
- };
-
- Drawable icon = Utils.loadDrawable(getActivity().getPackageManager(), iconPkg,
- iconResId);
- iconView.setImageDrawable(icon);
-
- messageView.setText(message);
-
- allowButton.setOnClickListener(clickListener);
- denyButton.setOnClickListener(clickListener);
- doNotAskCheckbox.setOnClickListener(clickListener);
-
- if (groupCount > 1) {
- currentGroupView.setVisibility(View.VISIBLE);
- currentGroupView.setText(getString(R.string.current_permission_template,
- groupIndex + 1, groupCount));
- } else {
- currentGroupView.setVisibility(View.INVISIBLE);
- }
-
- return content;
- }
-
- @Override
- public void onDismiss(DialogInterface dialog) {
- Activity activity = getActivity();
- if (activity != null) {
- ((OnRequestGrantPermissionGroupResult) getActivity())
- .onRequestGrantPermissionGroupResult(mGroupName, false);
- }
- }
-}
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java
new file mode 100644
index 00000000..dba459c2
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionViewHandler.java
@@ -0,0 +1,334 @@
+/*
+ * 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.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.packageinstaller.R;
+
+public final class GrantPermissionViewHandler implements OnClickListener {
+
+ public static final String ARG_GROUP_NAME = "ARG_GROUP_NAME";
+ public static final String ARG_GROUP_COUNT = "ARG_GROUP_COUNT";
+ public static final String ARG_GROUP_INDEX = "ARG_GROUP_INDEX";
+ public static final String ARG_GROUP_ICON = "ARG_GROUP_ICON";
+ public static final String ARG_GROUP_MESSAGE = "ARG_GROUP_MESSAGE";
+
+ // Animation parameters.
+ private static final long SIZE_START_DELAY = 300;
+ private static final long SIZE_START_LENGTH = 233;
+ private static final long FADE_OUT_START_DELAY = 300;
+ private static final long FADE_OUT_START_LENGTH = 217;
+ private static final long TRANSLATE_START_DELAY = 367;
+ private static final long TRANSLATE_LENGTH = 317;
+ private static final long GROUP_UPDATE_DELAY = 400;
+
+ private final OnRequestGrantPermissionGroupResult mResultListener;
+ private final Context mContext;
+
+ private String mGroupName;
+ private int mGroupCount;
+ private int mGroupIndex;
+ private Icon mGroupIcon;
+ private CharSequence mGroupMessage;
+
+ private ImageView mIconView;
+ private TextView mCurrentGroupView;
+ private TextView mMessageView;
+
+ private ViewHeightController mRootViewHeightController;
+ private ManualLayoutFrame mRootView;
+
+ // Needed for animation
+ private ViewGroup mDescContainer;
+ private ViewGroup mCurrentDesc;
+ private ViewGroup mNextDesc;
+
+ private ViewGroup mDialogContainer;
+
+ private final Runnable mUpdateGroup = new Runnable() {
+ @Override
+ public void run() {
+ updateGroup();
+ }
+ };
+
+ public interface OnRequestGrantPermissionGroupResult {
+ public void onRequestGrantPermissionGroupResult(String name, boolean granted);
+ }
+
+ public GrantPermissionViewHandler(OnRequestGrantPermissionGroupResult resultListener,
+ Context context) {
+ mResultListener = resultListener;
+ mContext = context;
+ }
+
+ public void onSaveInstanceState(Bundle arguments) {
+ arguments.putString(ARG_GROUP_NAME, mGroupName);
+ arguments.putInt(ARG_GROUP_COUNT, mGroupCount);
+ arguments.putInt(ARG_GROUP_INDEX, mGroupIndex);
+ arguments.putParcelable(ARG_GROUP_ICON, mGroupIcon);
+ arguments.putCharSequence(ARG_GROUP_MESSAGE, mGroupMessage);
+ }
+
+ public void loadSavedInstance(Bundle savedInstanceState) {
+ mGroupName = savedInstanceState.getString(ARG_GROUP_NAME);
+ mGroupMessage = savedInstanceState.getCharSequence(ARG_GROUP_MESSAGE);
+ mGroupIcon = savedInstanceState.getParcelable(ARG_GROUP_ICON);
+ mGroupCount = savedInstanceState.getInt(ARG_GROUP_COUNT);
+ mGroupIndex = savedInstanceState.getInt(ARG_GROUP_INDEX);
+ }
+
+ public void showPermission(String groupName, int groupCount, int groupIndex, Icon icon,
+ CharSequence message) {
+ mGroupName = groupName;
+ mGroupCount = groupCount;
+ mGroupIndex = groupIndex;
+ mGroupIcon = icon;
+ mGroupMessage = message;
+ // If this is a second (or later) permission and the views exist, then animate.
+ if (mIconView != null) {
+ if (mGroupIndex > 0) {
+ animateToPermission();
+ } else {
+ updateDescription();
+ updateGroup();
+ }
+ }
+ }
+
+ private void animateToPermission() {
+ if (mRootViewHeightController == null) {
+ // Allow height control of the real root view, not the root of what we inflate.
+ // Need to do it on the root view so that the background drawable of the dialog
+ // moves with the animation.
+ View realRootView = mRootView.getViewRootImpl().getView();
+ mRootViewHeightController = new ViewHeightController(realRootView);
+ mRootViewHeightController.setHeight(realRootView.getHeight());
+ }
+
+ // Grab the current height/y positions, then wait for the layout to change,
+ // so we can get the end height/y positions.
+ final SparseArray<Float> startPositions = getViewPositions();
+ final int startHeight = mRootView.getLayoutHeight();
+ mRootView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ mRootView.removeOnLayoutChangeListener(this);
+ SparseArray<Float> endPositions = getViewPositions();
+ int endHeight = mRootView.getLayoutHeight();
+ animateYPos(startPositions, endPositions, endHeight - startHeight);
+ }
+ });
+
+ // Fade out old description group and scale out the icon for it.
+ Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
+ android.R.interpolator.fast_out_linear_in);
+ mIconView.animate()
+ .scaleX(0)
+ .scaleY(0)
+ .setStartDelay(FADE_OUT_START_DELAY)
+ .setDuration(FADE_OUT_START_LENGTH)
+ .setInterpolator(interpolator)
+ .start();
+ mCurrentDesc.animate()
+ .alpha(0)
+ .setStartDelay(FADE_OUT_START_DELAY)
+ .setDuration(FADE_OUT_START_LENGTH)
+ .setInterpolator(interpolator)
+ .setListener(null)
+ .start();
+
+ // Update the index of the permission after the animations have started.
+ mCurrentGroupView.getHandler().postDelayed(mUpdateGroup, GROUP_UPDATE_DELAY);
+
+ // Add the new description and translate it in.
+ mNextDesc = (ViewGroup) LayoutInflater.from(mContext).inflate(
+ R.layout.permission_description, mDescContainer, false);
+
+ mMessageView = (TextView) mNextDesc.findViewById(R.id.permission_message);
+ mIconView = (ImageView) mNextDesc.findViewById(R.id.permission_icon);
+ updateDescription();
+
+ int width = mDescContainer.getRootView().getWidth();
+ mDescContainer.addView(mNextDesc);
+ mNextDesc.setTranslationX(width);
+ final View oldDesc = mCurrentDesc;
+ mCurrentDesc = mNextDesc;
+ mNextDesc.animate()
+ .translationX(0)
+ .setStartDelay(TRANSLATE_START_DELAY)
+ .setDuration(TRANSLATE_LENGTH)
+ .setInterpolator(AnimationUtils.loadInterpolator(mContext,
+ android.R.interpolator.linear_out_slow_in))
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // This is the longest animation, when it finishes, we are done.
+ mDescContainer.removeView(oldDesc);
+ }
+ })
+ .start();
+ }
+
+ private SparseArray<Float> getViewPositions() {
+ SparseArray<Float> locMap = new SparseArray<>();
+ final int N = mDialogContainer.getChildCount();
+ for (int i = 0; i < N; i++) {
+ View child = mDialogContainer.getChildAt(i);
+ if (child.getId() <= 0) {
+ // Only track views with ids.
+ continue;
+ }
+ locMap.put(child.getId(), child.getY());
+ }
+ return locMap;
+ }
+
+ private void animateYPos(SparseArray<Float> startPositions, SparseArray<Float> endPositions,
+ int heightDiff) {
+ final int N = startPositions.size();
+ for (int i = 0; i < N; i++) {
+ int key = startPositions.keyAt(i);
+ float start = startPositions.get(key);
+ float end = endPositions.get(key);
+ if (start != end) {
+ final View child = mDialogContainer.findViewById(key);
+ child.setTranslationY(start - end);
+ child.animate()
+ .setStartDelay(SIZE_START_DELAY)
+ .setDuration(SIZE_START_LENGTH)
+ .translationY(0)
+ .start();
+ }
+ }
+ mRootViewHeightController.animateAddHeight(heightDiff);
+ }
+
+ public View creatView() {
+ mRootView = (ManualLayoutFrame) LayoutInflater.from(mContext)
+ .inflate(R.layout.grant_permissions, null);
+
+ mDialogContainer = (ViewGroup) mRootView.findViewById(R.id.dialog_container);
+ mMessageView = (TextView) mRootView.findViewById(R.id.permission_message);
+ mIconView = (ImageView) mRootView.findViewById(R.id.permission_icon);
+ mCurrentGroupView = (TextView) mRootView.findViewById(R.id.current_page_text);
+
+ 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);
+ mRootView.findViewById(R.id.permission_deny_button).setOnClickListener(this);
+ mRootView.findViewById(R.id.do_not_ask_checkbox).setOnClickListener(this);
+
+ if (mGroupName != null) {
+ updateDescription();
+ updateGroup();
+ }
+
+ return mRootView;
+ }
+
+ private void updateDescription() {
+ mIconView.setImageDrawable(mGroupIcon.loadDrawable(mContext));
+ mMessageView.setText(mGroupMessage);
+ }
+
+ private void updateGroup() {
+ if (mGroupCount > 1) {
+ mCurrentGroupView.setVisibility(View.VISIBLE);
+ mCurrentGroupView.setText(mContext.getString(R.string.current_permission_template,
+ mGroupIndex + 1, mGroupCount));
+ } else {
+ mCurrentGroupView.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.permission_allow_button:
+ mResultListener.onRequestGrantPermissionGroupResult(mGroupName, true);
+ break;
+ case R.id.permission_deny_button:
+ mResultListener.onRequestGrantPermissionGroupResult(mGroupName, false);
+ break;
+ case R.id.do_not_ask_checkbox:
+ //TODO: Implement me.
+ break;
+
+ }
+ }
+
+ /**
+ * 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 final View mView;
+ private int mHeight;
+
+ public ViewHeightController(View view) {
+ mView = view;
+ mView.addOnLayoutChangeListener(this);
+ }
+
+ public void animateAddHeight(int heightDiff) {
+ if (heightDiff != 0) {
+ final int startHeight = mHeight;
+ final int endHeight = startHeight + heightDiff;
+ ObjectAnimator animator = ObjectAnimator.ofInt(this, "height",
+ startHeight, endHeight);
+ animator.setStartDelay(SIZE_START_DELAY);
+ animator.setDuration(SIZE_START_LENGTH);
+ animator.start();
+ }
+ }
+
+ public void setHeight(int height) {
+ mHeight = height;
+ updateTop();
+ }
+
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ // Ensure that the height never changes.
+ updateTop();
+ }
+
+ private void updateTop() {
+ mView.setTop(mView.getBottom() - mHeight);
+ }
+ }
+}
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
index 02951e9f..159a043f 100644
--- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
+++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java
@@ -17,14 +17,13 @@
package com.android.packageinstaller.permission.ui;
import android.app.Activity;
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentTransaction;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Icon;
import android.hardware.camera2.utils.ArrayUtils;
import android.os.Bundle;
import android.text.SpannableString;
@@ -39,12 +38,9 @@ import com.android.packageinstaller.permission.model.Permission;
import com.android.packageinstaller.permission.model.PermissionGroup;
public class GrantPermissionsActivity extends Activity implements
- GrantPermissionFragment.OnRequestGrantPermissionGroupResult {
+ GrantPermissionViewHandler.OnRequestGrantPermissionGroupResult {
private static final String LOG_TAG = "GrantPermissionsActivity";
- private static final String TAG_GRANT_PERMISSION_GROUP_FRAGMENT =
- "TAG_GRANT_PERMISSION_GROUP_FRAGMENT";
-
private static final int PERMISSION_GRANTED = 1;
private static final int PERMISSION_DENIED = 2;
private static final int PERMISSION_DENIED_RUNTIME = 3;
@@ -55,11 +51,14 @@ public class GrantPermissionsActivity extends Activity implements
private ArrayMap<String, GroupState> mRequestGrantPermissionGroups = new ArrayMap<>();
+ private final GrantPermissionViewHandler mViewHandler =
+ new GrantPermissionViewHandler(this, this);
private AppPermissions mAppPermissions;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ setFinishOnTouchOutside(false);
mRequestedPermissions = getIntent().getStringArrayExtra(
PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES);
@@ -94,6 +93,19 @@ public class GrantPermissionsActivity extends Activity implements
if (!showNextPermissionGroupFragment()) {
setResultAndFinish();
}
+ setContentView(mViewHandler.creatView());
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mViewHandler.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ mViewHandler.loadSavedInstance(savedInstanceState);
}
private boolean showNextPermissionGroupFragment() {
@@ -103,19 +115,6 @@ public class GrantPermissionsActivity extends Activity implements
GroupState groupState = mRequestGrantPermissionGroups.valueAt(i);
if (!groupState.mGroup.areRuntimePermissionsGranted()
&& groupState.mState == GroupState.STATE_UNKNOWN) {
- // Make sure adding the fragment we will remove is not in flight.
- getFragmentManager().executePendingTransactions();
-
- // Remove old grant fragment if such exists.
- FragmentTransaction transaction = getFragmentManager().beginTransaction();
- Fragment oldFragment = getFragmentManager().findFragmentByTag(
- TAG_GRANT_PERMISSION_GROUP_FRAGMENT);
- if (oldFragment != null) {
- transaction.remove(oldFragment);
- }
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
- transaction.commit();
-
CharSequence appLabel = mAppPermissions.getAppLabel();
SpannableString message = new SpannableString(getString(
R.string.permission_warning_template, appLabel,
@@ -127,15 +126,20 @@ public class GrantPermissionsActivity extends Activity implements
message.setSpan(new ForegroundColorSpan(color), appLabelStart,
appLabelStart + appLabelLength, 0);
- // Add the new grant fragment.
+ // Set the new grant view
// TODO: Use a real message for the action. We need group action APIs
- String pkg = groupState.mGroup.getIconPkg();
+ Resources resources;
+ try {
+ resources = getPackageManager().getResourcesForApplication(
+ groupState.mGroup.getIconPkg());
+ } catch (NameNotFoundException e) {
+ // Fallback to system.
+ resources = Resources.getSystem();
+ }
int icon = groupState.mGroup.getIconResId();
- DialogFragment newFragment = GrantPermissionFragment
- .newInstance(groupState.mGroup.getName(), groupCount, i,
- pkg, icon, message);
- newFragment.show(getFragmentManager(), TAG_GRANT_PERMISSION_GROUP_FRAGMENT);
+ mViewHandler.showPermission(groupState.mGroup.getName(), groupCount, i,
+ Icon.createWithResource(resources, icon), message);
return true;
}
}
diff --git a/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java b/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java
new file mode 100644
index 00000000..97049df8
--- /dev/null
+++ b/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java
@@ -0,0 +1,66 @@
+/*
+ * 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.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * Allows one standard layout pass, but afterwards holds getMeasuredHeight constant,
+ * however still allows drawing larger at the size needed by its children. This allows
+ * a dialog to tell the window the height is constant (with keeps its position constant)
+ * but allows the view to grow downwards for animation.
+ */
+public class ManualLayoutFrame extends FrameLayout {
+
+ private int mDesiredHeight;
+ private int mHeight;
+
+ public ManualLayoutFrame(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setClipChildren(false);
+ setClipToPadding(false);
+ }
+
+ public int getLayoutHeight() {
+ return mDesiredHeight;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ mDesiredHeight = getMeasuredHeight();
+ if (mHeight == 0 && mDesiredHeight != 0) {
+ // Record the first non-zero height, this will be the height henceforth.
+ mHeight = mDesiredHeight;
+ }
+ if (mHeight != 0) {
+ // Always report the same height
+ setMeasuredDimension(getMeasuredWidth(), mHeight);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ if (mDesiredHeight != 0) {
+ // Draw at height we expect to be.
+ setBottom(getTop() + mDesiredHeight);
+ bottom = top + mDesiredHeight;
+ }
+ super.onLayout(changed, left, top, right, bottom);
+ }
+}