-->
<!-- Entity header -->
-<RelativeLayout
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/entity_header"
style="@style/EntityHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingStart="@dimen/preference_no_icon_padding_start"
android:paddingTop="24dp"
android:paddingBottom="24dp">
- <ImageView
- android:id="@+id/entity_header_icon"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:scaleType="fitXY"
- android:layout_gravity="center_horizontal"
- android:antialias="true" />
+ <LinearLayout
+ android:id="@+id/entity_header_content"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:background="?android:attr/selectableItemBackground"
+ android:orientation="horizontal"
+ android:paddingStart="56dp">
+
+ <ImageView
+ android:id="@+id/entity_header_icon"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:scaleType="fitXY"
+ android:layout_gravity="center_horizontal"
+ android:antialias="true" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/entity_header_title"
+ style="@style/TextAppearance.EntityHeaderTitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="false"
+ android:ellipsize="marquee"
+ android:gravity="start"
+ android:textDirection="locale"
+ android:paddingTop="8dp" />
+
+ <TextView
+ android:id="@+id/install_type"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <TextView
+ android:id="@+id/entity_header_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ </LinearLayout>
+ </LinearLayout>
<LinearLayout
android:id="@+id/entity_header_links"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_alignParentEnd="true"
android:orientation="vertical">
<ImageButton
</LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_toEndOf="@id/entity_header_icon"
- android:layout_toStartOf="@id/entity_header_links"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/entity_header_title"
- style="@style/TextAppearance.EntityHeaderTitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="false"
- android:ellipsize="marquee"
- android:gravity="start"
- android:textDirection="locale"
- android:paddingTop="8dp" />
-
- <TextView
- android:id="@+id/install_type"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="start"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
- android:textColor="?android:attr/textColorSecondary" />
-
- <TextView
- android:id="@+id/entity_header_summary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="start"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
- android:textColor="?android:attr/textColorSecondary" />
-
- </LinearLayout>
-
-</RelativeLayout>
\ No newline at end of file
+</LinearLayout>
\ No newline at end of file
android:orientation="horizontal">
<LinearLayout
+ android:id="@+id/entity_header_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
+ android:background="?android:attr/selectableItemBackground"
android:orientation="vertical">
<ImageView
+++ /dev/null
-/*
- * 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.settings;
-
-import android.app.Fragment;
-import android.content.Intent;
-import android.os.Bundle;
-
-public class AppHeader {
-
- public static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton";
- // constant value that can be used to check return code from sub activity.
- private static final int INSTALLED_APP_DETAILS = 1;
-
- public static boolean includeAppInfo(final Fragment fragment) {
- Bundle args = fragment.getArguments();
- boolean showInfo = true;
- if (args != null && args.getBoolean(EXTRA_HIDE_INFO_BUTTON, false)) {
- showInfo = false;
- }
- Intent intent = fragment.getActivity().getIntent();
- if (intent != null && intent.getBooleanExtra(EXTRA_HIDE_INFO_BUTTON, false)) {
- showInfo = false;
- }
- return showInfo;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 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;
-
-import android.content.Context;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceViewHolder;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.TextView;
-
-public class MultiLinePreference extends Preference {
-
- public MultiLinePreference(Context ctx, AttributeSet attrs, int defStyle) {
- super(ctx, attrs, defStyle);
- }
-
- public MultiLinePreference(Context ctx, AttributeSet attrs) {
- super(ctx, attrs);
- }
-
- public MultiLinePreference(Context ctx) {
- super(ctx);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- super.onBindViewHolder(view);
-
- TextView textView = (TextView) view.findViewById(android.R.id.title);
- if (textView != null) {
- textView.setSingleLine(false);
- }
- }
-}
.setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
.setPackageName(mPackageName)
.setUid(mPackageInfo.applicationInfo.uid)
- .setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
+ .setHasAppInfoLink(true)
+ .setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE)
.done(activity, getPrefContext());
getPreferenceScreen().addPreference(pref);
}
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
-import com.android.settings.AppHeader;
import com.android.settings.DeviceAdminAdd;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
private static final int DLG_FORCE_STOP = DLG_BASE + 1;
private static final int DLG_DISABLE = DLG_BASE + 2;
private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3;
-
+ private static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton";
private static final String KEY_HEADER = "header_view";
private static final String KEY_INSTANT_APP_BUTTONS = "instant_app_buttons";
private static final String KEY_ACTION_BUTTONS = "action_buttons";
EntityHeaderController.newInstance(activity, this, mHeader.findViewById(R.id.entity_header))
.setRecyclerView(getListView(), getLifecycle())
.setPackageName(mPackageName)
+ .setHasAppInfoLink(false)
.setButtonActions(EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
EntityHeaderController.ActionType.ACTION_NONE)
.styleActionBar(activity)
// start new activity to manage app permissions
Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName);
- intent.putExtra(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
+ intent.putExtra(EXTRA_HIDE_INFO_BUTTON, true);
try {
getActivity().startActivityForResult(intent, SUB_INFO_FRAGMENT);
} catch (ActivityNotFoundException e) {
Bundle args = new Bundle();
args.putString(ARG_PACKAGE_NAME, appEntry.info.packageName);
args.putInt(ARG_PACKAGE_UID, appEntry.info.uid);
- args.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
SettingsActivity sa = (SettingsActivity) caller.getActivity();
sa.startPreferencePanel(caller, fragment.getName(), args, -1, title, caller,
import android.widget.Spinner;
import com.android.internal.app.procstats.ProcessStats;
-import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
args.putDouble(ProcessStatsDetail.EXTRA_MAX_MEMORY_USAGE,
memInfo.usedWeight * memInfo.weightToRam);
args.putDouble(ProcessStatsDetail.EXTRA_TOTAL_SCALE, memInfo.totalScale);
- args.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, !includeAppInfo);
activity.startPreferencePanel(null, ProcessStatsDetail.class.getName(), args,
R.string.memory_usage, null, null, 0);
}
.setUid(mApp.mUiTargetApp != null
? mApp.mUiTargetApp.uid
: UserHandle.USER_NULL)
- .setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
+ .setHasAppInfoLink(true)
+ .setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE)
.done(activity, getPrefContext());
getPreferenceScreen().addPreference(pref);
}
.newInstance(activity, this, null /* header */)
.setRecyclerView(getListView(), getLifecycle())
.setUid(uid)
- .setButtonActions(showInfoButton
- ? EntityHeaderController.ActionType.ACTION_APP_INFO
- : EntityHeaderController.ActionType.ACTION_NONE,
+ .setHasAppInfoLink(showInfoButton)
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
EntityHeaderController.ActionType.ACTION_NONE)
.setIcon(mIcon)
.setLabel(mLabel)
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
.setLabel(mAppRow.label)
.setPackageName(mAppRow.pkg)
.setUid(mAppRow.uid)
+ .setHasAppInfoLink(true)
.setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
.done(activity, getPrefContext());
channelPref.setSummary(getImportanceSummary(channel));
Bundle channelArgs = new Bundle();
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
- channelArgs.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
Intent channelIntent = Utils.onBuildStartFragmentIntent(getActivity(),
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.RingtonePreference;
import com.android.settings.Utils;
.setSummary(mAppRow.label)
.setPackageName(mAppRow.pkg)
.setUid(mAppRow.uid)
- .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_INFO,
- EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_NONE)
+ .setHasAppInfoLink(true)
.done(activity, getPrefContext());
getPreferenceScreen().addPreference(pref);
}
mImportance = findPreference(KEY_IMPORTANCE);
Bundle channelArgs = new Bundle();
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
- channelArgs.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, mChannel.getId());
mImportance.setEnabled(mSuspendedAppsAdmin == null && isChannelConfigurable(mChannel));
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
public class EntityHeaderController {
@IntDef({ActionType.ACTION_NONE,
- ActionType.ACTION_APP_INFO,
ActionType.ACTION_APP_PREFERENCE,
ActionType.ACTION_NOTIF_PREFERENCE})
@Retention(RetentionPolicy.SOURCE)
public @interface ActionType {
int ACTION_NONE = 0;
- int ACTION_APP_INFO = 1;
- int ACTION_APP_PREFERENCE = 2;
- int ACTION_NOTIF_PREFERENCE = 3;
+ int ACTION_APP_PREFERENCE = 1;
+ int ACTION_NOTIF_PREFERENCE = 2;
}
public static final String PREF_KEY_APP_HEADER = "pref_app_header";
@ActionType
private int mAction2;
+ private boolean mHasAppInfoLink;
+
private boolean mIsInstantApp;
/**
return this;
}
+ public EntityHeaderController setHasAppInfoLink(boolean hasAppInfoLink) {
+ mHasAppInfoLink = hasAppInfoLink;
+ return this;
+ }
+
public EntityHeaderController setButtonActions(@ActionType int action1,
@ActionType int action2) {
mAction1 = action1;
* Only binds entity header with button actions.
*/
public EntityHeaderController bindHeaderButtons() {
- ImageButton button1 = mHeader.findViewById(android.R.id.button1);
- ImageButton button2 = mHeader.findViewById(android.R.id.button2);
-
+ final View entityHeaderContent = mHeader.findViewById(R.id.entity_header_content);
+ final ImageButton button1 = mHeader.findViewById(android.R.id.button1);
+ final ImageButton button2 = mHeader.findViewById(android.R.id.button2);
+ bindAppInfoLink(entityHeaderContent);
bindButton(button1, mAction1);
bindButton(button2, mAction2);
return this;
}
+ private void bindAppInfoLink(View entityHeaderContent) {
+ if (!mHasAppInfoLink) {
+ // Caller didn't ask for app link, skip.
+ return;
+ }
+ if (entityHeaderContent == null
+ || mPackageName == null
+ || mPackageName.equals(Utils.OS_PKG)
+ || mUid == UserHandle.USER_NULL) {
+ Log.w(TAG, "Missing ingredients to build app info link, skip");
+ return;
+ }
+ entityHeaderContent.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AppInfoBase.startAppInfoFragment(
+ InstalledAppDetails.class, R.string.application_info_label,
+ mPackageName, mUid, mFragment, 0 /* request */,
+ mMetricsCategory);
+
+ }
+ });
+ return;
+ }
+
public EntityHeaderController styleActionBar(Activity activity) {
if (activity == null) {
Log.w(TAG, "No activity, cannot style actionbar.");
return;
}
switch (action) {
- case ActionType.ACTION_APP_INFO: {
- if (mPackageName == null || mPackageName.equals(Utils.OS_PKG)
- || mUid == UserHandle.USER_NULL
- || !AppHeader.includeAppInfo(mFragment)) {
- button.setVisibility(View.GONE);
- } else {
- button.setContentDescription(
- mAppContext.getString(R.string.application_info_label));
- button.setImageResource(com.android.settings.R.drawable.ic_info);
- button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- AppInfoBase.startAppInfoFragment(
- InstalledAppDetails.class, R.string.application_info_label,
- mPackageName, mUid, mFragment, 0 /* request */,
- mMetricsCategory);
-
- }
- });
- button.setVisibility(View.VISIBLE);
- }
- return;
- }
case ActionType.ACTION_NOTIF_PREFERENCE: {
if (mAppNotifPrefIntent == null) {
button.setVisibility(View.GONE);
import android.util.ArraySet;
import android.view.View;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.PackageManagerWrapper;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController;
-import com.android.settings.widget.EntityHeaderController.ActionType;
import com.android.settingslib.AppItem;
import org.junit.After;
import org.robolectric.util.ReflectionHelpers;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
- verify(mHeaderController).setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE);
+ verify(mHeaderController).setHasAppInfoLink(false);
}
@Test
ShadowEntityHeaderController.setUseMock(mHeaderController);
when(mHeaderController.setRecyclerView(any(), any())).thenReturn(mHeaderController);
when(mHeaderController.setUid(fakeUserId)).thenReturn(mHeaderController);
+ when(mHeaderController.setHasAppInfoLink(anyBoolean())).thenReturn(mHeaderController);
doReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS))
.when(mFragment)
mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
verify(mHeaderController)
- .setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE);
+ .setHasAppInfoLink(true);
verify(mHeaderController)
.setUid(fakeUserId);
}
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
}
@Test
- public void bindButton_noAppInfo_shouldNotShowButton() {
+ public void bindButton_noAppInfo_shouldNotAttachClickListener() {
final View appLinks = mLayoutInflater
.inflate(R.layout.settings_entity_header, null /* root */);
+ final Activity activity = mock(Activity.class);
+ when(mFragment.getActivity()).thenReturn(activity);
mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
mController.setPackageName(null)
+ .setHasAppInfoLink(true)
.setButtonActions(
- EntityHeaderController.ActionType.ACTION_APP_INFO,
+ EntityHeaderController.ActionType.ACTION_NONE,
EntityHeaderController.ActionType.ACTION_NONE);
mController.done(mActivity);
.isEqualTo(View.GONE);
assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
.isEqualTo(View.GONE);
- }
-
- @Test
- public void bindButton_hasAppInfo_shouldShowButton() {
- final View appLinks = mLayoutInflater
- .inflate(R.layout.settings_entity_header, null /* root */);
- when(mFragment.getActivity()).thenReturn(mock(Activity.class));
- mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
- mController.setPackageName("123")
- .setUid(UserHandle.USER_SYSTEM)
- .setButtonActions(
- EntityHeaderController.ActionType.ACTION_APP_INFO,
- EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
- mController.done(mActivity);
-
- assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
- .isEqualTo(View.VISIBLE);
- assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
- .isEqualTo(View.GONE);
+ appLinks.findViewById(R.id.entity_header_content).performClick();
+ verify(mFragment, never()).getActivity();
+ verify(activity, never()).startActivity(any(Intent.class));
}
@Test
- public void bindButton_hasAppInfo_shouldHaveContentDescription() {
+ public void bindButton_hasAppInfo_shouldAttachClickListener() {
final View appLinks = mLayoutInflater
.inflate(R.layout.settings_entity_header, null /* root */);
- when(mFragment.getActivity()).thenReturn(mock(Activity.class));
+ final Activity activity = mock(Activity.class);
+ when(mFragment.getActivity()).thenReturn(activity);
when(mContext.getString(eq(R.string.application_info_label))).thenReturn("App Info");
mController = EntityHeaderController.newInstance(mActivity, mFragment, appLinks);
mController.setPackageName("123")
.setUid(UserHandle.USER_SYSTEM)
+ .setHasAppInfoLink(true)
.setButtonActions(
- EntityHeaderController.ActionType.ACTION_APP_INFO,
- EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
+ EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_NONE);
mController.done(mActivity);
- assertThat(appLinks.findViewById(android.R.id.button1).getContentDescription().toString())
- .isEqualTo("App info");
+ appLinks.findViewById(R.id.entity_header_content).performClick();
+ verify(activity).startActivityForResultAsUser(
+ any(Intent.class), anyInt(), any(UserHandle.class));
}
@Test