From 8d1eee08f76e64a728be6f046e8d73fb957c594f Mon Sep 17 00:00:00 2001 From: Yuming Mao Date: Wed, 15 Aug 2018 15:10:23 +0800 Subject: [PATCH 01/23] Fix issue that read-only apns can be edited When entering to ApnEditor with ApnSettings#onPreferenceTreeClick(), subId is not passed. So invalid subId is used and it gets wrong carrier config values. To resolve this issue, remove unnecessary ApnSettings click event. The only click event for launching ApnEditor is ApnPreference click event. Test: manual - Check that the read-only APN can't be edited when tap the edge of the APN settings screen Bug: 117302653 Change-Id: I0a61b409539d6e4f6aa9860235e61c43c76640fa --- .../settings/network/ApnPreference.java | 30 +++++++------------ .../android/settings/network/ApnSettings.java | 13 +------- 2 files changed, 12 insertions(+), 31 deletions(-) diff --git a/src/com/android/settings/network/ApnPreference.java b/src/com/android/settings/network/ApnPreference.java index ee53ca9518f..27d275f83c6 100755 --- a/src/com/android/settings/network/ApnPreference.java +++ b/src/com/android/settings/network/ApnPreference.java @@ -27,15 +27,12 @@ import android.telephony.SubscriptionManager; import android.util.AttributeSet; import android.util.Log; import android.view.View; -import android.view.View.OnClickListener; import android.widget.CompoundButton; import android.widget.RadioButton; -import android.widget.RelativeLayout; import com.android.settings.R; -public class ApnPreference extends Preference implements - CompoundButton.OnCheckedChangeListener, OnClickListener { +public class ApnPreference extends Preference implements CompoundButton.OnCheckedChangeListener { final static String TAG = "ApnPreference"; private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -81,11 +78,6 @@ public class ApnPreference extends Preference implements rb.setVisibility(View.GONE); } } - - View textLayout = view.findViewById(R.id.text_layout); - if ((textLayout != null) && textLayout instanceof RelativeLayout) { - textLayout.setOnClickListener(this); - } } public boolean isChecked() { @@ -115,16 +107,16 @@ public class ApnPreference extends Preference implements } } - public void onClick(android.view.View v) { - if ((v != null) && (R.id.text_layout == v.getId())) { - Context context = getContext(); - if (context != null) { - int pos = Integer.parseInt(getKey()); - Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos); - Intent editIntent = new Intent(Intent.ACTION_EDIT, url); - editIntent.putExtra(ApnSettings.SUB_ID, mSubId); - context.startActivity(editIntent); - } + @Override + protected void onClick() { + super.onClick(); + Context context = getContext(); + if (context != null) { + int pos = Integer.parseInt(getKey()); + Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos); + Intent editIntent = new Intent(Intent.ACTION_EDIT, url); + editIntent.putExtra(ApnSettings.SUB_ID, mSubId); + context.startActivity(editIntent); } } diff --git a/src/com/android/settings/network/ApnSettings.java b/src/com/android/settings/network/ApnSettings.java index 013ae8cc7c8..5bc52cc9d3d 100755 --- a/src/com/android/settings/network/ApnSettings.java +++ b/src/com/android/settings/network/ApnSettings.java @@ -21,7 +21,6 @@ import android.app.Dialog; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.ContentResolver; -import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; @@ -64,8 +63,7 @@ import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import java.util.ArrayList; -public class ApnSettings extends RestrictedSettingsFragment implements - Preference.OnPreferenceChangeListener { +public class ApnSettings extends RestrictedSettingsFragment { static final String TAG = "ApnSettings"; public static final String EXTRA_POSITION = "position"; @@ -312,7 +310,6 @@ public class ApnSettings extends RestrictedSettingsFragment implements pref.setTitle(name); pref.setSummary(apn); pref.setPersistent(false); - pref.setOnPreferenceChangeListener(this); pref.setSubId(subId); boolean selectable = ((type == null) || !type.equals("mms")); @@ -404,14 +401,6 @@ public class ApnSettings extends RestrictedSettingsFragment implements startActivity(intent); } - @Override - public boolean onPreferenceTreeClick(Preference preference) { - int pos = Integer.parseInt(preference.getKey()); - Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos); - startActivity(new Intent(Intent.ACTION_EDIT, url)); - return true; - } - public boolean onPreferenceChange(Preference preference, Object newValue) { Log.d(TAG, "onPreferenceChange(): Preference - " + preference + ", newValue - " + newValue + ", newValue type - " From 5eb6e6dcc71c507d0070bec961b098bd54a24d6f Mon Sep 17 00:00:00 2001 From: Stanley Wang Date: Fri, 2 Nov 2018 19:39:25 +0800 Subject: [PATCH 02/23] Modified the PrintJobSettingsFragment Test: manual Test: make RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.print Change-Id: Ide889b273be21421753cec99ce391adb756ab05c --- res/xml/print_job_settings.xml | 7 +- .../PrintJobMessagePreferenceController.java | 47 ++++ .../print/PrintJobPreferenceController.java | 115 ++++++++++ .../PrintJobPreferenceControllerBase.java | 99 +++++++++ .../print/PrintJobSettingsFragment.java | 202 ++---------------- ...intJobMessagePreferenceControllerTest.java | 113 ++++++++++ .../PrintJobPreferenceControllerTest.java | 189 ++++++++++++++++ 7 files changed, 587 insertions(+), 185 deletions(-) create mode 100644 src/com/android/settings/print/PrintJobMessagePreferenceController.java create mode 100644 src/com/android/settings/print/PrintJobPreferenceController.java create mode 100644 src/com/android/settings/print/PrintJobPreferenceControllerBase.java create mode 100644 tests/robotests/src/com/android/settings/print/PrintJobMessagePreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/print/PrintJobPreferenceControllerTest.java diff --git a/res/xml/print_job_settings.xml b/res/xml/print_job_settings.xml index 32a80a73d09..877cd628689 100644 --- a/res/xml/print_job_settings.xml +++ b/res/xml/print_job_settings.xml @@ -19,13 +19,16 @@ android:title="@string/print_print_job"> + android:key="print_job_preference" + android:title="@string/print_print_job" + settings:controller="com.android.settings.print.PrintJobPreferenceController"> + android:selectable="false" + settings:controller="com.android.settings.print.PrintJobMessagePreferenceController"> diff --git a/src/com/android/settings/print/PrintJobMessagePreferenceController.java b/src/com/android/settings/print/PrintJobMessagePreferenceController.java new file mode 100644 index 00000000000..9573e5d6007 --- /dev/null +++ b/src/com/android/settings/print/PrintJobMessagePreferenceController.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018 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.print; + +import android.content.Context; +import android.print.PrintJob; +import android.print.PrintJobInfo; +import android.text.TextUtils; + +public class PrintJobMessagePreferenceController extends PrintJobPreferenceControllerBase { + + public PrintJobMessagePreferenceController(Context context, String key) { + super(context, key); + } + + @Override + protected void updateUi() { + final PrintJob printJob = getPrintJob(); + + if (printJob == null) { + mFragment.finish(); + return; + } + + if (printJob.isCancelled() || printJob.isCompleted()) { + mFragment.finish(); + return; + } + + final PrintJobInfo info = printJob.getInfo(); + final CharSequence status = info.getStatus(mContext.getPackageManager()); + mPreference.setVisible(!TextUtils.isEmpty(status)); + mPreference.setSummary(status); + } +} diff --git a/src/com/android/settings/print/PrintJobPreferenceController.java b/src/com/android/settings/print/PrintJobPreferenceController.java new file mode 100644 index 00000000000..0eff0d6d612 --- /dev/null +++ b/src/com/android/settings/print/PrintJobPreferenceController.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2018 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.print; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.print.PrintJob; +import android.print.PrintJobInfo; +import android.text.format.DateUtils; + +import com.android.settings.R; + +import java.text.DateFormat; + +public class PrintJobPreferenceController extends PrintJobPreferenceControllerBase { + + public PrintJobPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + protected void updateUi() { + final PrintJob printJob = getPrintJob(); + + if (printJob == null) { + mFragment.finish(); + return; + } + + if (printJob.isCancelled() || printJob.isCompleted()) { + mFragment.finish(); + return; + } + + PrintJobInfo info = printJob.getInfo(); + + switch (info.getState()) { + case PrintJobInfo.STATE_CREATED: { + mPreference.setTitle(mContext.getString( + R.string.print_configuring_state_title_template, info.getLabel())); + } + break; + case PrintJobInfo.STATE_QUEUED: + case PrintJobInfo.STATE_STARTED: { + if (!printJob.getInfo().isCancelling()) { + mPreference.setTitle(mContext.getString( + R.string.print_printing_state_title_template, info.getLabel())); + } else { + mPreference.setTitle(mContext.getString( + R.string.print_cancelling_state_title_template, info.getLabel())); + } + } + break; + + case PrintJobInfo.STATE_FAILED: { + mPreference.setTitle(mContext.getString( + R.string.print_failed_state_title_template, info.getLabel())); + } + break; + + case PrintJobInfo.STATE_BLOCKED: { + if (!printJob.getInfo().isCancelling()) { + mPreference.setTitle(mContext.getString( + R.string.print_blocked_state_title_template, info.getLabel())); + } else { + mPreference.setTitle(mContext.getString( + R.string.print_cancelling_state_title_template, info.getLabel())); + } + } + break; + } + + mPreference.setSummary(mContext.getString(R.string.print_job_summary, + info.getPrinterName(), DateUtils.formatSameDayTime( + info.getCreationTime(), info.getCreationTime(), DateFormat.SHORT, + DateFormat.SHORT))); + + TypedArray a = mContext.obtainStyledAttributes(new int[]{ + android.R.attr.colorControlNormal}); + int tintColor = a.getColor(0, 0); + a.recycle(); + + switch (info.getState()) { + case PrintJobInfo.STATE_QUEUED: + case PrintJobInfo.STATE_STARTED: { + Drawable icon = mContext.getDrawable(com.android.internal.R.drawable.ic_print); + icon.setTint(tintColor); + mPreference.setIcon(icon); + break; + } + + case PrintJobInfo.STATE_FAILED: + case PrintJobInfo.STATE_BLOCKED: { + Drawable icon = mContext.getDrawable( + com.android.internal.R.drawable.ic_print_error); + icon.setTint(tintColor); + mPreference.setIcon(icon); + break; + } + } + } +} diff --git a/src/com/android/settings/print/PrintJobPreferenceControllerBase.java b/src/com/android/settings/print/PrintJobPreferenceControllerBase.java new file mode 100644 index 00000000000..0726a19f4d1 --- /dev/null +++ b/src/com/android/settings/print/PrintJobPreferenceControllerBase.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2018 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.print; + +import android.content.Context; +import android.print.PrintJob; +import android.print.PrintJobId; +import android.print.PrintManager; +import android.util.Log; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +public abstract class PrintJobPreferenceControllerBase extends BasePreferenceController implements + LifecycleObserver, OnStart, OnStop, PrintManager.PrintJobStateChangeListener { + private static final String TAG = "PrintJobPrefCtrlBase"; + + private static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID"; + + private final PrintManager mPrintManager; + protected Preference mPreference; + protected PrintJobSettingsFragment mFragment; + protected PrintJobId mPrintJobId; + + public PrintJobPreferenceControllerBase(Context context, String key) { + super(context, key); + mPrintManager = ((PrintManager) mContext.getSystemService( + Context.PRINT_SERVICE)).getGlobalPrintManagerForUser(mContext.getUserId()); + } + + @Override + public void onStart() { + mPrintManager.addPrintJobStateChangeListener(this); + updateUi(); + } + + @Override + public void onStop() { + mPrintManager.removePrintJobStateChangeListener(this); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public void onPrintJobStateChanged(PrintJobId printJobId) { + updateUi(); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + } + + public void init(PrintJobSettingsFragment fragment) { + mFragment = fragment; + processArguments(); + } + + protected PrintJob getPrintJob() { + return mPrintManager.getPrintJob(mPrintJobId); + } + + protected abstract void updateUi(); + + private void processArguments() { + String printJobId = mFragment.getArguments().getString(EXTRA_PRINT_JOB_ID); + if (printJobId == null) { + printJobId = mFragment.getActivity().getIntent().getStringExtra(EXTRA_PRINT_JOB_ID); + + if (printJobId == null) { + Log.w(TAG, EXTRA_PRINT_JOB_ID + " not set"); + mFragment.finish(); + return; + } + } + mPrintJobId = PrintJobId.unflattenFromString(printJobId); + } +} diff --git a/src/com/android/settings/print/PrintJobSettingsFragment.java b/src/com/android/settings/print/PrintJobSettingsFragment.java index ba0172ba560..1d6ff5a1451 100644 --- a/src/com/android/settings/print/PrintJobSettingsFragment.java +++ b/src/com/android/settings/print/PrintJobSettingsFragment.java @@ -17,114 +17,59 @@ package com.android.settings.print; import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.print.PrintJob; -import android.print.PrintJobId; -import android.print.PrintJobInfo; -import android.print.PrintManager; -import android.print.PrintManager.PrintJobStateChangeListener; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.util.Log; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; - -import androidx.preference.Preference; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; -import com.android.settings.SettingsPreferenceFragment; - -import java.text.DateFormat; +import com.android.settings.dashboard.DashboardFragment; /** * Fragment for management of a print job. */ -public class PrintJobSettingsFragment extends SettingsPreferenceFragment { - private static final String LOG_TAG = PrintJobSettingsFragment.class.getSimpleName(); +public class PrintJobSettingsFragment extends DashboardFragment { + private static final String TAG = "PrintJobSettingsFragment"; private static final int MENU_ITEM_ID_CANCEL = 1; private static final int MENU_ITEM_ID_RESTART = 2; - private static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID"; + @Override + protected int getPreferenceScreenResId() { + return R.xml.print_job_settings; + } - private static final String PRINT_JOB_PREFERENCE = "print_job_preference"; - private static final String PRINT_JOB_MESSAGE_PREFERENCE = "print_job_message_preference"; + @Override + protected String getLogTag() { + return TAG; + } - private final PrintJobStateChangeListener mPrintJobStateChangeListener = - new PrintJobStateChangeListener() { - @Override - public void onPrintJobStateChanged(PrintJobId printJobId) { - updateUi(); - } - }; - - private PrintManager mPrintManager; - - private Preference mPrintJobPreference; - private Preference mMessagePreference; - - private PrintJobId mPrintJobId; + @Override + public void onAttach(Context context) { + super.onAttach(context); + use(PrintJobPreferenceController.class).init(this); + use(PrintJobMessagePreferenceController.class).init(this); + } @Override public int getMetricsCategory() { return MetricsEvent.PRINT_JOB_SETTINGS; } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = super.onCreateView(inflater, container, savedInstanceState); - - addPreferencesFromResource(R.xml.print_job_settings); - mPrintJobPreference = findPreference(PRINT_JOB_PREFERENCE); - mMessagePreference = findPreference(PRINT_JOB_MESSAGE_PREFERENCE); - - mPrintManager = ((PrintManager) getActivity().getSystemService( - Context.PRINT_SERVICE)).getGlobalPrintManagerForUser( - getActivity().getUserId()); - - getActivity().getActionBar().setTitle(R.string.print_print_job); - - processArguments(); - - setHasOptionsMenu(true); - - return view; - } - @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); getListView().setEnabled(false); } - @Override - public void onStart() { - super.onStart(); - mPrintManager.addPrintJobStateChangeListener( - mPrintJobStateChangeListener); - updateUi(); - } - - @Override - public void onStop() { - super.onStop(); - mPrintManager.removePrintJobStateChangeListener( - mPrintJobStateChangeListener); - } - @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); - PrintJob printJob = getPrintJob(); + final PrintJob printJob = use(PrintJobPreferenceController.class).getPrintJob(); if (printJob == null) { return; } @@ -144,7 +89,7 @@ public class PrintJobSettingsFragment extends SettingsPreferenceFragment { @Override public boolean onOptionsItemSelected(MenuItem item) { - PrintJob printJob = getPrintJob(); + final PrintJob printJob = use(PrintJobPreferenceController.class).getPrintJob(); if (printJob != null) { switch (item.getItemId()) { @@ -164,113 +109,4 @@ public class PrintJobSettingsFragment extends SettingsPreferenceFragment { return super.onOptionsItemSelected(item); } - - private void processArguments() { - String printJobId = getArguments().getString(EXTRA_PRINT_JOB_ID); - if (printJobId == null) { - printJobId = getIntent().getStringExtra(EXTRA_PRINT_JOB_ID); - - if (printJobId == null) { - Log.w(LOG_TAG, EXTRA_PRINT_JOB_ID + " not set"); - finish(); - return; - } - } - - - mPrintJobId = PrintJobId.unflattenFromString(printJobId); - } - - private PrintJob getPrintJob() { - return mPrintManager.getPrintJob(mPrintJobId); - } - - private void updateUi() { - PrintJob printJob = getPrintJob(); - - if (printJob == null) { - finish(); - return; - } - - if (printJob.isCancelled() || printJob.isCompleted()) { - finish(); - return; - } - - PrintJobInfo info = printJob.getInfo(); - - switch (info.getState()) { - case PrintJobInfo.STATE_CREATED: { - mPrintJobPreference.setTitle(getString( - R.string.print_configuring_state_title_template, info.getLabel())); - } break; - case PrintJobInfo.STATE_QUEUED: - case PrintJobInfo.STATE_STARTED: { - if (!printJob.getInfo().isCancelling()) { - mPrintJobPreference.setTitle(getString( - R.string.print_printing_state_title_template, info.getLabel())); - } else { - mPrintJobPreference.setTitle(getString( - R.string.print_cancelling_state_title_template, info.getLabel())); - } - } break; - - case PrintJobInfo.STATE_FAILED: { - mPrintJobPreference.setTitle(getString( - R.string.print_failed_state_title_template, info.getLabel())); - } break; - - case PrintJobInfo.STATE_BLOCKED: { - if (!printJob.getInfo().isCancelling()) { - mPrintJobPreference.setTitle(getString( - R.string.print_blocked_state_title_template, info.getLabel())); - } else { - mPrintJobPreference.setTitle(getString( - R.string.print_cancelling_state_title_template, info.getLabel())); - } - } break; - } - - mPrintJobPreference.setSummary(getString(R.string.print_job_summary, - info.getPrinterName(), DateUtils.formatSameDayTime( - info.getCreationTime(), info.getCreationTime(), DateFormat.SHORT, - DateFormat.SHORT))); - - TypedArray a = getActivity().obtainStyledAttributes(new int[]{ - android.R.attr.colorControlNormal}); - int tintColor = a.getColor(0, 0); - a.recycle(); - - switch (info.getState()) { - case PrintJobInfo.STATE_QUEUED: - case PrintJobInfo.STATE_STARTED: { - Drawable icon = getActivity().getDrawable(com.android.internal.R.drawable.ic_print); - icon.setTint(tintColor); - mPrintJobPreference.setIcon(icon); - break; - } - - case PrintJobInfo.STATE_FAILED: - case PrintJobInfo.STATE_BLOCKED: { - Drawable icon = getActivity().getDrawable( - com.android.internal.R.drawable.ic_print_error); - icon.setTint(tintColor); - mPrintJobPreference.setIcon(icon); - break; - } - } - - CharSequence status = info.getStatus(getPackageManager()); - if (!TextUtils.isEmpty(status)) { - if (getPreferenceScreen().findPreference(PRINT_JOB_MESSAGE_PREFERENCE) == null) { - getPreferenceScreen().addPreference(mMessagePreference); - } - mMessagePreference.setSummary(status); - } else { - getPreferenceScreen().removePreference(mMessagePreference); - } - - getActivity().invalidateOptionsMenu(); - } } diff --git a/tests/robotests/src/com/android/settings/print/PrintJobMessagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/print/PrintJobMessagePreferenceControllerTest.java new file mode 100644 index 00000000000..50dd38b183b --- /dev/null +++ b/tests/robotests/src/com/android/settings/print/PrintJobMessagePreferenceControllerTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2018 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.print; + +import static androidx.lifecycle.Lifecycle.Event.ON_START; +import static androidx.lifecycle.Lifecycle.Event.ON_STOP; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.print.PrintJob; +import android.print.PrintJobInfo; +import android.print.PrintManager; + +import androidx.lifecycle.LifecycleOwner; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class PrintJobMessagePreferenceControllerTest { + private static final String PREF_KEY = "print_job_message_preference"; + + @Mock + private PrintManager mPrintManager; + @Mock + private PrintJob mPrintJob; + @Mock + private PrintJobInfo mPrintJobInfo; + @Mock + private PreferenceScreen mScreen; + + private Context mContext; + private PrintJobMessagePreferenceController mController; + private Preference mPreference; + private LifecycleOwner mLifecycleOwner; + private Lifecycle mLifecycle; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + mPreference = new Preference(mContext); + when(mContext.getSystemService(Context.PRINT_SERVICE)).thenReturn(mPrintManager); + when(mPrintManager.getGlobalPrintManagerForUser(anyInt())).thenReturn(mPrintManager); + when(mPrintManager.getPrintJob(anyObject())).thenReturn(mPrintJob); + when(mPrintJob.getInfo()).thenReturn(mPrintJobInfo); + mController = new PrintJobMessagePreferenceController(mContext, PREF_KEY); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + mController.displayPreference(mScreen); + mLifecycleOwner = () -> mLifecycle; + mLifecycle = new Lifecycle(mLifecycleOwner); + mLifecycle.addObserver(mController); + } + + @Test + public void onStartStop_shouldRegisterPrintStateListener() { + mLifecycle.handleLifecycleEvent(ON_START); + mLifecycle.handleLifecycleEvent(ON_STOP); + + verify(mPrintManager).addPrintJobStateChangeListener(mController); + verify(mPrintManager).removePrintJobStateChangeListener(mController); + } + + @Test + public void updateUi_visiblePreference() { + when(mPrintJobInfo.getStatus(anyObject())).thenReturn("TestPrint"); + mLifecycle.handleLifecycleEvent(ON_START); + + assertThat(mPreference.isVisible()).isTrue(); + + mLifecycle.handleLifecycleEvent(ON_STOP); + } + + @Test + public void updateUi_invisiblePreference() { + when(mPrintJobInfo.getStatus(anyObject())).thenReturn(null); + mLifecycle.handleLifecycleEvent(ON_START); + + assertThat(mPreference.isVisible()).isFalse(); + + mLifecycle.handleLifecycleEvent(ON_STOP); + } +} diff --git a/tests/robotests/src/com/android/settings/print/PrintJobPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/print/PrintJobPreferenceControllerTest.java new file mode 100644 index 00000000000..fc92eb3cc8f --- /dev/null +++ b/tests/robotests/src/com/android/settings/print/PrintJobPreferenceControllerTest.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2018 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.print; + +import static androidx.lifecycle.Lifecycle.Event.ON_START; +import static androidx.lifecycle.Lifecycle.Event.ON_STOP; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.print.PrintJob; +import android.print.PrintJobInfo; +import android.print.PrintManager; + +import androidx.lifecycle.LifecycleOwner; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class PrintJobPreferenceControllerTest { + private static final String PREF_KEY = "print_job_preference"; + + @Mock + private PrintManager mPrintManager; + @Mock + private PrintJob mPrintJob; + @Mock + private PrintJobInfo mPrintJobInfo; + @Mock + private PreferenceScreen mScreen; + + private Context mContext; + private LifecycleOwner mLifecycleOwner; + private Lifecycle mLifecycle; + private PrintJobPreferenceController mController; + private Preference mPreference; + private String mTestLabel; + + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + mPreference = new Preference(mContext); + mTestLabel = "PrintTest"; + when(mContext.getSystemService(Context.PRINT_SERVICE)).thenReturn(mPrintManager); + when(mPrintManager.getGlobalPrintManagerForUser(anyInt())).thenReturn(mPrintManager); + when(mPrintManager.getPrintJob(anyObject())).thenReturn(mPrintJob); + when(mPrintJob.getInfo()).thenReturn(mPrintJobInfo); + mController = new PrintJobPreferenceController(mContext, PREF_KEY); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + when(mPrintJobInfo.getLabel()).thenReturn(mTestLabel); + mController.displayPreference(mScreen); + mLifecycleOwner = () -> mLifecycle; + mLifecycle = new Lifecycle(mLifecycleOwner); + mLifecycle.addObserver(mController); + } + + @Test + public void onStartStop_shouldRegisterPrintStateListener() { + mLifecycle.handleLifecycleEvent(ON_START); + mLifecycle.handleLifecycleEvent(ON_STOP); + + verify(mPrintManager).addPrintJobStateChangeListener(mController); + verify(mPrintManager).removePrintJobStateChangeListener(mController); + } + + @Test + public void updateUi_jobState_STATE_CREATED() { + when(mPrintJobInfo.getState()).thenReturn(PrintJobInfo.STATE_CREATED); + + mController.onStart(); + String title = mContext.getString( + R.string.print_configuring_state_title_template, mTestLabel); + + assertThat(mPreference.getTitle()).isEqualTo(title); + } + + @Test + public void updateUi_jobState_STATE_QUEUED() { + when(mPrintJobInfo.getState()).thenReturn(PrintJobInfo.STATE_QUEUED); + + mController.onStart(); + String title = mContext.getString( + R.string.print_printing_state_title_template, mTestLabel); + + assertThat(mPreference.getTitle()).isEqualTo(title); + } + + @Test + public void updateUi_jobState_STATE_STARTED() { + when(mPrintJobInfo.getState()).thenReturn(PrintJobInfo.STATE_STARTED); + + mController.onStart(); + String title = mContext.getString( + R.string.print_printing_state_title_template, mTestLabel); + + assertThat(mPreference.getTitle()).isEqualTo(title); + } + + @Test + public void updateUi_jobState_STATE_QUEUED_and_jobInfo_CANCELLING() { + when(mPrintJobInfo.getState()).thenReturn(PrintJobInfo.STATE_QUEUED); + when(mPrintJobInfo.isCancelling()).thenReturn(true); + + mController.onStart(); + String title = mContext.getString( + R.string.print_cancelling_state_title_template, mTestLabel); + + assertThat(mPreference.getTitle()).isEqualTo(title); + } + + @Test + public void updateUi_jobState_STATE_STARTED_and_jobInfo_CANCELLING() { + when(mPrintJobInfo.getState()).thenReturn(PrintJobInfo.STATE_STARTED); + when(mPrintJobInfo.isCancelling()).thenReturn(true); + + mController.onStart(); + String title = mContext.getString( + R.string.print_cancelling_state_title_template, mTestLabel); + + assertThat(mPreference.getTitle()).isEqualTo(title); + } + + @Test + public void updateUi_jobState_STATE_FAILED() { + when(mPrintJobInfo.getState()).thenReturn(PrintJobInfo.STATE_FAILED); + + mController.onStart(); + String title = mContext.getString( + R.string.print_failed_state_title_template, mTestLabel); + + assertThat(mPreference.getTitle()).isEqualTo(title); + } + + @Test + public void updateUi_jobState_STATE_BLOCKED() { + when(mPrintJobInfo.getState()).thenReturn(PrintJobInfo.STATE_BLOCKED); + + mController.onStart(); + String title = mContext.getString( + R.string.print_blocked_state_title_template, mTestLabel); + + assertThat(mPreference.getTitle()).isEqualTo(title); + } + + @Test + public void updateUi_jobState_STATE_BLOCKED_and_jobInfo_CANCELLING() { + when(mPrintJobInfo.getState()).thenReturn(PrintJobInfo.STATE_BLOCKED); + when(mPrintJobInfo.isCancelling()).thenReturn(true); + + mController.onStart(); + String title = mContext.getString( + R.string.print_cancelling_state_title_template, mTestLabel); + + assertThat(mPreference.getTitle()).isEqualTo(title); + } +} From 57eb049bec9c1d35c31038be75e1bd960d80eec7 Mon Sep 17 00:00:00 2001 From: Amin Shaikh Date: Fri, 2 Nov 2018 11:04:33 -0400 Subject: [PATCH 03/23] Delete Directory access Settings. Bug: 111892460 Test: m RunSettingsRoboTests Change-Id: I6ffa5a4b69fa7b3ee9d9a058fa075b60fbd2b0a3 --- AndroidManifest.xml | 10 - res/values/strings.xml | 9 - res/xml/directory_access_details.xml | 20 -- res/xml/special_access.xml | 10 - src/com/android/settings/Settings.java | 1 - .../AppStateDirectoryAccessBridge.java | 99 ------ .../applications/AppStorageSettings.java | 15 - .../applications/DirectoryAccessDetails.java | 323 ------------------ .../manageapplications/AppFilterRegistry.java | 10 - .../ManageApplications.java | 16 - .../core/gateway/SettingsGateway.java | 2 - ...randfather_not_implementing_index_provider | 1 - tests/uitests/assets/search_results_list | 3 +- 13 files changed, 1 insertion(+), 518 deletions(-) delete mode 100644 res/xml/directory_access_details.xml delete mode 100644 src/com/android/settings/applications/AppStateDirectoryAccessBridge.java delete mode 100644 src/com/android/settings/applications/DirectoryAccessDetails.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index aa98c62f49d..362ca11cca7 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2962,16 +2962,6 @@ android:value="true" /> - - - - - - - - ANGLE enabled application: %1$s - - Directory access - - directory access - - - %1$s (%2$s) - diff --git a/res/xml/directory_access_details.xml b/res/xml/directory_access_details.xml deleted file mode 100644 index 4448ba65aeb..00000000000 --- a/res/xml/directory_access_details.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml index a6c2159360b..57e673fdba3 100644 --- a/res/xml/special_access.xml +++ b/res/xml/special_access.xml @@ -120,16 +120,6 @@ android:value="com.android.settings.Settings$VrListenersSettingsActivity" /> - - - - mPackages; - - @Override - public void init() { - throw new UnsupportedOperationException("Need to call constructor that takes context"); - } - - @Override - public void init(Context context) { - mPackages = null; - final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) - .authority(AUTHORITY).appendPath(TABLE_PACKAGES).appendPath("*") - .build(); - try (Cursor cursor = context.getContentResolver().query(providerUri, - TABLE_PACKAGES_COLUMNS, null, null)) { - if (cursor == null) { - Log.w(TAG, "Didn't get cursor for " + providerUri); - return; - } - final int count = cursor.getCount(); - if (count == 0) { - if (DEBUG) { - Log.d(TAG, "No packages anymore (was " + mPackages + ")"); - } - return; - } - mPackages = new ArraySet<>(count); - while (cursor.moveToNext()) { - mPackages.add(cursor.getString(TABLE_PACKAGES_COL_PACKAGE)); - } - if (DEBUG) { - Log.d(TAG, "init(): " + mPackages); - } - } - } - - - @Override - public boolean filterApp(AppEntry info) { - return mPackages != null && mPackages.contains(info.info.packageName); - } - }; -} diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java index e24a2109f60..c926da38a7b 100644 --- a/src/com/android/settings/applications/AppStorageSettings.java +++ b/src/com/android/settings/applications/AppStorageSettings.java @@ -18,13 +18,10 @@ package com.android.settings.applications; import static android.content.pm.ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA; import static android.content.pm.ApplicationInfo.FLAG_SYSTEM; -import static android.os.storage.StorageVolume.ScopedAccessProviderContract.AUTHORITY; -import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.GrantedUriPermission; -import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -32,7 +29,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -461,17 +457,6 @@ public class AppStorageSettings extends AppInfoWithHeader Context.ACTIVITY_SERVICE); am.clearGrantedUriPermissions(packageName); - - // Also update the Scoped Directory Access UI permissions - final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) - .authority(AUTHORITY).appendPath(TABLE_PERMISSIONS).appendPath("*") - .build(); - Log.v(TAG, "Asking " + providerUri + " to delete permissions for " + packageName); - final int deleted = context.getContentResolver().delete(providerUri, null, new String[] { - packageName - }); - Log.d(TAG, "Deleted " + deleted + " entries for package " + packageName); - // Update UI refreshGrantedUriPermissions(); } diff --git a/src/com/android/settings/applications/DirectoryAccessDetails.java b/src/com/android/settings/applications/DirectoryAccessDetails.java deleted file mode 100644 index f158d81780a..00000000000 --- a/src/com/android/settings/applications/DirectoryAccessDetails.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (C) 2018 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.applications; - -import static android.os.storage.StorageVolume.ScopedAccessProviderContract.AUTHORITY; -import static android.os.storage.StorageVolume.ScopedAccessProviderContract.COL_GRANTED; -import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS; -import static android.os.storage.StorageVolume.ScopedAccessProviderContract - .TABLE_PERMISSIONS_COLUMNS; -import static android.os.storage.StorageVolume.ScopedAccessProviderContract - .TABLE_PERMISSIONS_COL_DIRECTORY; -import static android.os.storage.StorageVolume.ScopedAccessProviderContract - .TABLE_PERMISSIONS_COL_GRANTED; -import static android.os.storage.StorageVolume.ScopedAccessProviderContract - .TABLE_PERMISSIONS_COL_PACKAGE; -import static android.os.storage.StorageVolume.ScopedAccessProviderContract - .TABLE_PERMISSIONS_COL_VOLUME_UUID; - -import static com.android.settings.applications.AppStateDirectoryAccessBridge.DEBUG; -import static com.android.settings.applications.AppStateDirectoryAccessBridge.VERBOSE; - -import android.annotation.Nullable; -import android.app.Activity; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.os.storage.StorageManager; -import android.os.storage.VolumeInfo; -import android.util.IconDrawableFactory; -import android.util.Log; -import android.util.Pair; - -import androidx.appcompat.app.AlertDialog; -import androidx.preference.Preference; -import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; - -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.settings.R; -import com.android.settings.widget.EntityHeaderController; -import com.android.settings.widget.EntityHeaderController.ActionType; -import com.android.settingslib.applications.AppUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Detailed settings for an app's directory access permissions (A.K.A Scoped Directory Access). - * - *

Currently, it shows the entry for which the user denied access with the "Do not ask again" - * flag checked on: the user than can use the settings toggle to reset that deniel. - * - *

This fragments dynamically lists all such permissions, starting with one preference per - * directory in the primary storage, then adding additional entries for the external volumes (one - * entry for the whole volume). - */ -// TODO(b/72055774): add unit tests -public class DirectoryAccessDetails extends AppInfoBase { - - @SuppressWarnings("hiding") - private static final String TAG = "DirectoryAccessDetails"; - - private boolean mCreated; - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - if (mCreated) { - Log.w(TAG, "onActivityCreated(): ignoring duplicate call"); - return; - } - mCreated = true; - if (mPackageInfo == null) { - Log.w(TAG, "onActivityCreated(): no package info"); - return; - } - final Activity activity = getActivity(); - final Preference pref = EntityHeaderController - .newInstance(activity, this, /* header= */ null ) - .setRecyclerView(getListView(), getSettingsLifecycle()) - .setIcon(IconDrawableFactory.newInstance(getPrefContext()) - .getBadgedIcon(mPackageInfo.applicationInfo)) - .setLabel(mPackageInfo.applicationInfo.loadLabel(mPm)) - .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo)) - .setPackageName(mPackageName) - .setUid(mPackageInfo.applicationInfo.uid) - .setHasAppInfoLink(false) - .setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE) - .done(activity, getPrefContext()); - getPreferenceScreen().addPreference(pref); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - addPreferencesFromResource(R.xml.directory_access_details); - - } - - @Override - protected boolean refreshUi() { - final Context context = getPrefContext(); - final PreferenceScreen prefsGroup = getPreferenceScreen(); - prefsGroup.removeAll(); - - final Map externalVolumes = new HashMap<>(); - - final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) - .authority(AUTHORITY).appendPath(TABLE_PERMISSIONS).appendPath("*") - .build(); - // Query provider for entries. - try (Cursor cursor = context.getContentResolver().query(providerUri, - TABLE_PERMISSIONS_COLUMNS, null, new String[] { mPackageName }, null)) { - if (cursor == null) { - Log.w(TAG, "Didn't get cursor for " + mPackageName); - return true; - } - final int count = cursor.getCount(); - if (count == 0) { - // This setting screen should not be reached if there was no permission, so just - // ignore it - Log.w(TAG, "No permissions for " + mPackageName); - return true; - } - - while (cursor.moveToNext()) { - final String pkg = cursor.getString(TABLE_PERMISSIONS_COL_PACKAGE); - final String uuid = cursor.getString(TABLE_PERMISSIONS_COL_VOLUME_UUID); - final String dir = cursor.getString(TABLE_PERMISSIONS_COL_DIRECTORY); - final boolean granted = cursor.getInt(TABLE_PERMISSIONS_COL_GRANTED) == 1; - if (VERBOSE) { - Log.v(TAG, "Pkg:" + pkg + " uuid: " + uuid + " dir: " + dir - + " granted:" + granted); - } - - if (!mPackageName.equals(pkg)) { - // Sanity check, shouldn't happen - Log.w(TAG, "Ignoring " + uuid + "/" + dir + " due to package mismatch: " - + "expected " + mPackageName + ", got " + pkg); - continue; - } - - if (uuid == null) { - if (dir == null) { - // Sanity check, shouldn't happen - Log.wtf(TAG, "Ignoring permission on primary storage root"); - } else { - // Primary storage entry: add right away - prefsGroup.addPreference(newPreference(context, dir, providerUri, - /* uuid= */ null, dir, granted, /* children= */ null)); - } - } else { - // External volume entry: save it for later. - ExternalVolume externalVolume = externalVolumes.get(uuid); - if (externalVolume == null) { - externalVolume = new ExternalVolume(uuid); - externalVolumes.put(uuid, externalVolume); - } - if (dir == null) { - // Whole volume - externalVolume.granted = granted; - } else { - // Directory only - externalVolume.children.add(new Pair<>(dir, granted)); - } - } - } - } - - if (VERBOSE) { - Log.v(TAG, "external volumes: " + externalVolumes); - } - - if (externalVolumes.isEmpty()) { - // We're done! - return true; - } - - // Add entries from external volumes - - // Query StorageManager to get the user-friendly volume names. - final StorageManager sm = context.getSystemService(StorageManager.class); - final List volumes = sm.getVolumes(); - if (volumes.isEmpty()) { - Log.w(TAG, "StorageManager returned no secondary volumes"); - return true; - } - final Map volumeNames = new HashMap<>(volumes.size()); - for (VolumeInfo volume : volumes) { - final String uuid = volume.getFsUuid(); - if (uuid == null) continue; // Primary storage; not used. - - String name = sm.getBestVolumeDescription(volume); - if (name == null) { - Log.w(TAG, "No description for " + volume + "; using uuid instead: " + uuid); - name = uuid; - } - volumeNames.put(uuid, name); - } - if (VERBOSE) { - Log.v(TAG, "UUID -> name mapping: " + volumeNames); - } - - for (ExternalVolume volume : externalVolumes.values()) { - final String volumeName = volumeNames.get(volume.uuid); - if (volumeName == null) { - Log.w(TAG, "Ignoring entry for invalid UUID: " + volume.uuid); - continue; - } - // First add the pref for the whole volume... - final PreferenceCategory category = new PreferenceCategory(context); - prefsGroup.addPreference(category); - final Set children = new HashSet<>(volume.children.size()); - category.addPreference(newPreference(context, volumeName, providerUri, volume.uuid, - /* dir= */ null, volume.granted, children)); - - // ... then the children prefs - volume.children.forEach((pair) -> { - final String dir = pair.first; - final String name = context.getResources() - .getString(R.string.directory_on_volume, volumeName, dir); - final SwitchPreference childPref = - newPreference(context, name, providerUri, volume.uuid, dir, pair.second, - /* children= */ null); - category.addPreference(childPref); - children.add(childPref); - }); - } - return true; - } - - private SwitchPreference newPreference(Context context, String title, Uri providerUri, - String uuid, String dir, boolean granted, @Nullable Set children) { - final SwitchPreference pref = new SwitchPreference(context); - pref.setKey(String.format("%s:%s", uuid, dir)); - pref.setTitle(title); - pref.setChecked(granted); - pref.setOnPreferenceChangeListener((unused, value) -> { - if (!Boolean.class.isInstance(value)) { - // Sanity check - Log.wtf(TAG, "Invalid value from switch: " + value); - return true; - } - final boolean newValue = ((Boolean) value).booleanValue(); - - resetDoNotAskAgain(context, newValue, providerUri, uuid, dir); - if (children != null) { - // When parent is granted, children should be hidden; and vice versa - final boolean newChildValue = !newValue; - for (SwitchPreference child : children) { - child.setVisible(newChildValue); - } - } - return true; - }); - return pref; - } - - private void resetDoNotAskAgain(Context context, boolean newValue, Uri providerUri, - @Nullable String uuid, @Nullable String directory) { - if (DEBUG) { - Log.d(TAG, "Asking " + providerUri + " to update " + uuid + "/" + directory + " to " - + newValue); - } - final ContentValues values = new ContentValues(1); - values.put(COL_GRANTED, newValue); - final int updated = context.getContentResolver().update(providerUri, values, - null, new String[] { mPackageName, uuid, directory }); - if (DEBUG) { - Log.d(TAG, "Updated " + updated + " entries for " + uuid + "/" + directory); - } - } - - @Override - protected AlertDialog createDialog(int id, int errorCode) { - return null; - } - - @Override - public int getMetricsCategory() { - return MetricsEvent.APPLICATIONS_DIRECTORY_ACCESS_DETAIL; - } - - private static class ExternalVolume { - final String uuid; - final List> children = new ArrayList<>(); - boolean granted; - - ExternalVolume(String uuid) { - this.uuid = uuid; - } - - @Override - public String toString() { - return "ExternalVolume: [uuid=" + uuid + ", granted=" + granted + - ", children=" + children + "]"; - } - } -} diff --git a/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java b/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java index 7d1e159ffe0..0d2bcab3129 100644 --- a/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java +++ b/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java @@ -19,7 +19,6 @@ package com.android.settings.applications.manageapplications; import androidx.annotation.IntDef; import com.android.settings.R; -import com.android.settings.applications.AppStateDirectoryAccessBridge; import com.android.settings.applications.AppStateInstallAppsBridge; import com.android.settings.applications.AppStateNotificationBridge; import com.android.settings.applications.AppStateOverlayBridge; @@ -70,7 +69,6 @@ public class AppFilterRegistry { public static final int FILTER_APPS_WITH_OVERLAY = 11; public static final int FILTER_APPS_WRITE_SETTINGS = 12; public static final int FILTER_APPS_INSTALL_SOURCES = 13; - public static final int FILTER_APP_HAS_DIRECTORY_ACCESS = 14; public static final int FILTER_APP_CAN_CHANGE_WIFI_STATE = 15; public static final int FILTER_APPS_BLOCKED = 16; // Next id: 17 @@ -170,12 +168,6 @@ public class AppFilterRegistry { FILTER_APPS_INSTALL_SOURCES, R.string.filter_install_sources_apps); - // Apps that interacted with directory access permissions (A.K.A. Scoped Directory Access) - mFilters[FILTER_APP_HAS_DIRECTORY_ACCESS] = new AppFilterItem( - AppStateDirectoryAccessBridge.FILTER_APP_HAS_DIRECTORY_ACCESS, - FILTER_APP_HAS_DIRECTORY_ACCESS, - R.string.filter_install_sources_apps); - mFilters[FILTER_APP_CAN_CHANGE_WIFI_STATE] = new AppFilterItem( AppStateChangeWifiStateBridge.FILTER_CHANGE_WIFI_STATE, FILTER_APP_CAN_CHANGE_WIFI_STATE, @@ -208,8 +200,6 @@ public class AppFilterRegistry { return FILTER_APPS_WRITE_SETTINGS; case ManageApplications.LIST_TYPE_MANAGE_SOURCES: return FILTER_APPS_INSTALL_SOURCES; - case ManageApplications.LIST_TYPE_DIRECTORY_ACCESS: - return FILTER_APP_HAS_DIRECTORY_ACCESS; case ManageApplications.LIST_TYPE_WIFI_ACCESS: return FILTER_APP_CAN_CHANGE_WIFI_STATE; case ManageApplications.LIST_TYPE_NOTIFICATION: diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index 44ea575a825..6b2fb916b1b 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -90,7 +90,6 @@ import com.android.settings.SettingsActivity; import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppStateAppOpsBridge.PermissionState; import com.android.settings.applications.AppStateBaseBridge; -import com.android.settings.applications.AppStateDirectoryAccessBridge; import com.android.settings.applications.AppStateInstallAppsBridge; import com.android.settings.applications.AppStateNotificationBridge; import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState; @@ -101,7 +100,6 @@ import com.android.settings.applications.AppStateUsageBridge.UsageState; import com.android.settings.applications.AppStateWriteSettingsBridge; import com.android.settings.applications.AppStorageSettings; import com.android.settings.applications.DefaultAppSettings; -import com.android.settings.applications.DirectoryAccessDetails; import com.android.settings.applications.InstalledAppCounter; import com.android.settings.applications.UsageAccessDetails; import com.android.settings.applications.appinfo.AppInfoDashboardFragment; @@ -218,7 +216,6 @@ public class ManageApplications extends InstrumentedFragment public static final int LIST_TYPE_GAMES = 9; public static final int LIST_TYPE_MOVIES = 10; public static final int LIST_TYPE_PHOTOGRAPHY = 11; - public static final int LIST_TYPE_DIRECTORY_ACCESS = 12; public static final int LIST_TYPE_WIFI_ACCESS = 13; // List types that should show instant apps. @@ -293,9 +290,6 @@ public class ManageApplications extends InstrumentedFragment mListType = LIST_TYPE_PHOTOGRAPHY; mSortOrder = R.id.sort_order_size; mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT); - } else if (className.equals(Settings.DirectoryAccessSettingsActivity.class.getName())) { - mListType = LIST_TYPE_DIRECTORY_ACCESS; - screenTitle = R.string.directory_access; } else if (className.equals(Settings.ChangeWifiStateActivity.class.getName())) { mListType = LIST_TYPE_WIFI_ACCESS; screenTitle = R.string.change_wifi_state_title; @@ -479,8 +473,6 @@ public class ManageApplications extends InstrumentedFragment return MetricsEvent.SYSTEM_ALERT_WINDOW_APPS; case LIST_TYPE_MANAGE_SOURCES: return MetricsEvent.MANAGE_EXTERNAL_SOURCES; - case LIST_TYPE_DIRECTORY_ACCESS: - return MetricsEvent.DIRECTORY_ACCESS; case LIST_TYPE_WIFI_ACCESS: return MetricsEvent.CONFIGURE_WIFI; default: @@ -578,9 +570,6 @@ public class ManageApplications extends InstrumentedFragment case LIST_TYPE_PHOTOGRAPHY: startAppInfoFragment(AppStorageSettings.class, R.string.storage_photos_videos); break; - case LIST_TYPE_DIRECTORY_ACCESS: - startAppInfoFragment(DirectoryAccessDetails.class, R.string.directory_access); - break; case LIST_TYPE_WIFI_ACCESS: startAppInfoFragment(ChangeWifiStateDetails.class, R.string.change_wifi_state_title); @@ -916,8 +905,6 @@ public class ManageApplications extends InstrumentedFragment mExtraInfoBridge = new AppStateWriteSettingsBridge(mContext, mState, this); } else if (mManageApplications.mListType == LIST_TYPE_MANAGE_SOURCES) { mExtraInfoBridge = new AppStateInstallAppsBridge(mContext, mState, this); - } else if (mManageApplications.mListType == LIST_TYPE_DIRECTORY_ACCESS) { - mExtraInfoBridge = new AppStateDirectoryAccessBridge(mState, this); } else if (mManageApplications.mListType == LIST_TYPE_WIFI_ACCESS) { mExtraInfoBridge = new AppStateChangeWifiStateBridge(mContext, mState, this); } else { @@ -1360,9 +1347,6 @@ public class ManageApplications extends InstrumentedFragment case LIST_TYPE_MANAGE_SOURCES: holder.setSummary(ExternalSourcesDetails.getPreferenceSummary(mContext, entry)); break; - case LIST_TYPE_DIRECTORY_ACCESS: - holder.setSummary(null); - break; case LIST_TYPE_WIFI_ACCESS: holder.setSummary(ChangeWifiStateDetails.getSummary(mContext, entry)); break; diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index 434697359bb..f61cb0c464d 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -34,7 +34,6 @@ import com.android.settings.accounts.ChooseAccountFragment; import com.android.settings.accounts.ManagedProfileSettings; import com.android.settings.applications.AppAndNotificationDashboardFragment; import com.android.settings.applications.DefaultAppSettings; -import com.android.settings.applications.DirectoryAccessDetails; import com.android.settings.applications.ProcessStatsSummary; import com.android.settings.applications.ProcessStatsUi; import com.android.settings.applications.UsageAccessDetails; @@ -258,7 +257,6 @@ public class SettingsGateway { LockscreenDashboardFragment.class.getName(), BluetoothDeviceDetailsFragment.class.getName(), DataUsageList.class.getName(), - DirectoryAccessDetails.class.getName(), ToggleBackupSettingFragment.class.getName(), PreviouslyConnectedDeviceDashboardFragment.class.getName(), }; diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider index 6f4deca9adc..f9301a2af33 100644 --- a/tests/robotests/assets/grandfather_not_implementing_index_provider +++ b/tests/robotests/assets/grandfather_not_implementing_index_provider @@ -15,7 +15,6 @@ com.android.settings.applications.appinfo.WriteSettingsDetails com.android.settings.applications.AppLaunchSettings com.android.settings.applications.AppStorageSettings com.android.settings.applications.ConfirmConvertToFbe -com.android.settings.applications.DirectoryAccessDetails com.android.settings.applications.ProcessStatsDetail com.android.settings.applications.ProcessStatsSummary com.android.settings.applications.ProcessStatsUi diff --git a/tests/uitests/assets/search_results_list b/tests/uitests/assets/search_results_list index a0cc894f705..a8bf6f52abf 100644 --- a/tests/uitests/assets/search_results_list +++ b/tests/uitests/assets/search_results_list @@ -166,7 +166,6 @@ Device name;device_name Device security;security_category Device theme;theme Dial pad tones;dial_pad_tones -Directory access;special_app_directory_access Disable Bluetooth A2DP hardware offload;bluetooth_disable_a2dp_hw_offload Disable HW overlays;disable_overlays Disable USB audio routing;usb_audio @@ -620,4 +619,4 @@ Your access to this device;device_access_category  ;auto_brightness_video  ;battery_header  ;battery_tip - ;feature_flag_category \ No newline at end of file + ;feature_flag_category From f2f00313bb3669347991cf07a5d31273088c380f Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Tue, 16 Oct 2018 14:17:15 -0700 Subject: [PATCH 04/23] packages/apps/Settings: Add logic and strings to support WPA3 and OWE Add and update Wi-Fi security strings, and add logic to enable WPA3 and OWE. Modified WPA2-PSK to WPA2-Personal, and added WPA3-Personal, Enhanced Open and WPA3-Enterprise. Bug: 112195778 Test: Basic functional tests Change-Id: Ia97761a7f0a9e2fee768dfaf3578a2f1090d29c6 --- res/values/arrays.xml | 5 +- .../settings/wifi/WifiConfigController.java | 49 +++++++++++++++++-- .../android/settings/wifi/WifiSettings.java | 12 +++-- ...etherSecurityPreferenceControllerTest.java | 10 ++-- 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 94d915c965c..c3faabad9f9 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -215,10 +215,12 @@ @string/wifi_security_none + @string/wifi_security_owe @string/wifi_security_wep @string/wifi_security_psk_generic + @string/wifi_security_sae @string/wifi_security_eap - + @string/wifi_security_eap_suiteb @@ -228,6 +230,7 @@ @string/wifi_security_none @string/wifi_security_wep @string/wifi_security_psk_generic + @string/wifi_security_sae diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java index 4b93fc1796d..70837a6a810 100644 --- a/src/com/android/settings/wifi/WifiConfigController.java +++ b/src/com/android/settings/wifi/WifiConfigController.java @@ -454,6 +454,13 @@ public class WifiConfigController implements TextWatcher, return false; } + boolean isValidSaePassword(String password) { + if (password.length() >= 1 && password.length() <= 63) { + return true; + } + return false; + } + boolean isSubmittable() { boolean enabled = false; boolean passwordInvalid = false; @@ -461,7 +468,9 @@ public class WifiConfigController implements TextWatcher, && ((mAccessPointSecurity == AccessPoint.SECURITY_WEP && mPasswordView.length() == 0) || (mAccessPointSecurity == AccessPoint.SECURITY_PSK - && !isValidPsk(mPasswordView.getText().toString())))) { + && !isValidPsk(mPasswordView.getText().toString())) + || (mAccessPointSecurity == AccessPoint.SECURITY_SAE + && !isValidSaePassword(mPasswordView.getText().toString())))) { passwordInvalid = true; } if ((mSsidView != null && mSsidView.length() == 0) @@ -475,7 +484,9 @@ public class WifiConfigController implements TextWatcher, } else { enabled = ipAndProxyFieldsAreValid(); } - if (mAccessPointSecurity == AccessPoint.SECURITY_EAP && mEapCaCertSpinner != null + if ((mAccessPointSecurity == AccessPoint.SECURITY_EAP || + mAccessPointSecurity == AccessPoint.SECURITY_EAP_SUITE_B) + && mEapCaCertSpinner != null && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) { String caCertSelection = (String) mEapCaCertSpinner.getSelectedItem(); if (caCertSelection.equals(mUnspecifiedCertString)) { @@ -492,7 +503,9 @@ public class WifiConfigController implements TextWatcher, enabled = false; } } - if (mAccessPointSecurity == AccessPoint.SECURITY_EAP && mEapUserCertSpinner != null + if ((mAccessPointSecurity == AccessPoint.SECURITY_EAP || + mAccessPointSecurity == AccessPoint.SECURITY_EAP_SUITE_B) + && mEapUserCertSpinner != null && mView.findViewById(R.id.l_user_cert).getVisibility() != View.GONE && mEapUserCertSpinner.getSelectedItem().equals(mUnspecifiedCertString)) { // Disallow submit if the user has not selected a user certificate for an EAP network @@ -590,8 +603,18 @@ public class WifiConfigController implements TextWatcher, break; case AccessPoint.SECURITY_EAP: + case AccessPoint.SECURITY_EAP_SUITE_B: config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); + if (mAccessPointSecurity == AccessPoint.SECURITY_EAP_SUITE_B) { + config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192); + config.requirePMF = true; + config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); + config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); + config.allowedGroupMgmtCiphers.set(WifiConfiguration.GroupMgmtCipher + .BIP_GMAC_256); + config.allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_RSA); + } config.enterpriseConfig = new WifiEnterpriseConfig(); int eapMethod = mEapMethodSpinner.getSelectedItemPosition(); int phase2Method = mPhase2Spinner.getSelectedItemPosition(); @@ -700,6 +723,20 @@ public class WifiConfigController implements TextWatcher, config.enterpriseConfig.setPassword(mPasswordView.getText().toString()); } break; + case AccessPoint.SECURITY_SAE: + config.allowedKeyManagement.set(KeyMgmt.SAE); + config.requirePMF = true; + if (mPasswordView.length() != 0) { + String password = mPasswordView.getText().toString(); + config.preSharedKey = '"' + password + '"'; + } + break; + + case AccessPoint.SECURITY_OWE: + config.allowedKeyManagement.set(KeyMgmt.OWE); + config.requirePMF = true; + break; + default: return null; } @@ -851,7 +888,8 @@ public class WifiConfigController implements TextWatcher, } private void showSecurityFields() { - if (mAccessPointSecurity == AccessPoint.SECURITY_NONE) { + if (mAccessPointSecurity == AccessPoint.SECURITY_NONE || + mAccessPointSecurity == AccessPoint.SECURITY_OWE) { mView.findViewById(R.id.security_fields).setVisibility(View.GONE); return; } @@ -870,7 +908,8 @@ public class WifiConfigController implements TextWatcher, } } - if (mAccessPointSecurity != AccessPoint.SECURITY_EAP) { + if (mAccessPointSecurity != AccessPoint.SECURITY_EAP && + mAccessPointSecurity != AccessPoint.SECURITY_EAP_SUITE_B) { mView.findViewById(R.id.eap).setVisibility(View.GONE); return; } diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java index f097d5b810c..1c9a5e136c0 100644 --- a/src/com/android/settings/wifi/WifiSettings.java +++ b/src/com/android/settings/wifi/WifiSettings.java @@ -488,7 +488,8 @@ public class WifiSettings extends RestrictedSettingsFragment menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify); NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(getActivity()); if (nfcAdapter != null && nfcAdapter.isEnabled() && - mSelectedAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) { + (!(mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) || + (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_OWE))) { // Only allow writing of NFC tags for password-protected networks. menu.add(Menu.NONE, MENU_ID_WRITE_NFC, 0, R.string.wifi_menu_write_to_nfc); } @@ -506,7 +507,8 @@ public class WifiSettings extends RestrictedSettingsFragment boolean isSavedNetwork = mSelectedAccessPoint.isSaved(); if (isSavedNetwork) { connect(mSelectedAccessPoint.getConfig(), isSavedNetwork); - } else if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) { + } else if ((mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) || + (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_OWE)) { /** Bypass dialog for unsecured networks */ mSelectedAccessPoint.generateOpenNetworkConfig(); connect(mSelectedAccessPoint.getConfig(), isSavedNetwork); @@ -552,7 +554,8 @@ public class WifiSettings extends RestrictedSettingsFragment * networks, or Passpoint provided networks. */ WifiConfiguration config = mSelectedAccessPoint.getConfig(); - if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) { + if ((mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) || + (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_OWE)) { mSelectedAccessPoint.generateOpenNetworkConfig(); connect(mSelectedAccessPoint.getConfig(), mSelectedAccessPoint.isSaved()); } else if (mSelectedAccessPoint.isSaved() && config != null @@ -772,7 +775,8 @@ public class WifiSettings extends RestrictedSettingsFragment preference.setKey(key); preference.setOrder(index); if (mOpenSsid != null && mOpenSsid.equals(accessPoint.getSsidStr()) - && accessPoint.getSecurity() != AccessPoint.SECURITY_NONE) { + && (accessPoint.getSecurity() != AccessPoint.SECURITY_NONE && + accessPoint.getSecurity() != AccessPoint.SECURITY_OWE)) { if (!accessPoint.isSaved() || isDisabledByWrongPassword(accessPoint)) { onPreferenceTreeClick(preference); mOpenSsid = null; diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java index f8131850fe3..e8d13dfe218 100644 --- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSecurityPreferenceControllerTest.java @@ -66,7 +66,7 @@ public class WifiTetherSecurityPreferenceControllerTest { public void onPreferenceChange_securityValueUpdated() { mController.onPreferenceChange(mPreference, WPA2_PSK); assertThat(mController.getSecurityType()).isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK); - assertThat(mPreference.getSummary()).isEqualTo("WPA2 PSK"); + assertThat(mPreference.getSummary()).isEqualTo("WPA2-Personal"); mController.onPreferenceChange(mPreference, NONE); assertThat(mController.getSecurityType()).isEqualTo(WifiConfiguration.KeyMgmt.NONE); @@ -75,11 +75,11 @@ public class WifiTetherSecurityPreferenceControllerTest { @Test public void updateDisplay_preferenceUpdated() { - // test defaulting to WPA2 PSK on new config + // test defaulting to WPA2-Personal on new config when(mWifiManager.getWifiApConfiguration()).thenReturn(null); mController.updateDisplay(); assertThat(mController.getSecurityType()).isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK); - assertThat(mPreference.getSummary()).isEqualTo("WPA2 PSK"); + assertThat(mPreference.getSummary()).isEqualTo("WPA2-Personal"); // test open tether network when(mWifiManager.getWifiApConfiguration()).thenReturn(mConfig); @@ -89,11 +89,11 @@ public class WifiTetherSecurityPreferenceControllerTest { assertThat(mController.getSecurityType()).isEqualTo(WifiConfiguration.KeyMgmt.NONE); assertThat(mPreference.getSummary()).isEqualTo("None"); - // test WPA2 PSK tether network + // test WPA2-Personal tether network mConfig.allowedKeyManagement.clear(); mConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK); mController.updateDisplay(); assertThat(mController.getSecurityType()).isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK); - assertThat(mPreference.getSummary()).isEqualTo("WPA2 PSK"); + assertThat(mPreference.getSummary()).isEqualTo("WPA2-Personal"); } } From b8d59fc9f814a0d093e01ac6f5484f48b8e3fea4 Mon Sep 17 00:00:00 2001 From: Pengquan Meng Date: Mon, 5 Nov 2018 14:01:11 -0800 Subject: [PATCH 05/23] Replace some configs with CarrierConfig Replace the following config with CarrierConfig - config_enabled_lte - config_support_tdscdma - config_support_tdscdma_on_roaming_networks - carrier settings activity package/class name Bug: 115429501 Test: make -j40 ROBOTEST_FILTER=telephony RunSettingsRoboTests Change-Id: I3d973f926813c01fff6fcff50b3392c4eff69eb8 --- res/values/config.xml | 8 ---- res/values/strings.xml | 3 -- ...nabledNetworkModePreferenceController.java | 4 +- .../network/telephony/MobileNetworkUtils.java | 45 ++++++++----------- .../telephony/MobileNetworkUtilsTest.java | 3 +- 5 files changed, 22 insertions(+), 41 deletions(-) diff --git a/res/values/config.xml b/res/values/config.xml index b496080ea68..b9a69f105e8 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -136,12 +136,4 @@ true - - - - false - - false - - diff --git a/res/values/strings.xml b/res/values/strings.xml index e828ac2b677..7e37f5b3ff5 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10187,9 +10187,6 @@ Global - - - Available networks diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java index b077dd526fc..b323f910af5 100644 --- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java +++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java @@ -180,7 +180,7 @@ public class EnabledNetworkModePreferenceController extends BasePreferenceContro preference.setEntryValues( R.array.enabled_networks_tdscdma_values); } else if (!carrierConfig.getBoolean(CarrierConfigManager.KEY_PREFER_2G_BOOL) - && !resources.getBoolean(R.bool.config_enabled_lte)) { + && !carrierConfig.getBoolean(CarrierConfigManager.KEY_LTE_ENABLED_BOOL)) { preference.setEntries(R.array.enabled_networks_except_gsm_lte_choices); preference.setEntryValues(R.array.enabled_networks_except_gsm_lte_values); } else if (!carrierConfig.getBoolean(CarrierConfigManager.KEY_PREFER_2G_BOOL)) { @@ -190,7 +190,7 @@ public class EnabledNetworkModePreferenceController extends BasePreferenceContro preference.setEntries(select); preference.setEntryValues( R.array.enabled_networks_except_gsm_values); - } else if (!resources.getBoolean(R.bool.config_enabled_lte)) { + } else if (!carrierConfig.getBoolean(CarrierConfigManager.KEY_LTE_ENABLED_BOOL)) { preference.setEntries( R.array.enabled_networks_except_lte_choices); preference.setEntryValues( diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java index 689799eb96a..dc184d3df3f 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java +++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java @@ -27,6 +27,7 @@ import android.database.Cursor; import android.os.PersistableBundle; import android.os.SystemProperties; import android.provider.Settings; +import android.service.carrier.CarrierMessagingService; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; @@ -329,28 +330,11 @@ public class MobileNetworkUtils { * settings */ public static boolean isWorldMode(Context context, int subId) { - final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class) - .createForSubscriptionId(subId); - boolean worldModeOn = false; - final String configString = context.getString(R.string.config_world_mode); - - if (!TextUtils.isEmpty(configString)) { - String[] configArray = configString.split(";"); - // Check if we have World mode configuration set to True only or config is set to True - // and SIM GID value is also set and matches to the current SIM GID. - if (configArray != null && - ((configArray.length == 1 && configArray[0].equalsIgnoreCase("true")) - || (configArray.length == 2 && !TextUtils.isEmpty(configArray[1]) - && telephonyManager != null - && configArray[1].equalsIgnoreCase( - telephonyManager.getGroupIdLevel1())))) { - worldModeOn = true; - } - } - - Log.d(TAG, "isWorldMode=" + worldModeOn); - - return worldModeOn; + final PersistableBundle carrierConfig = context.getSystemService( + CarrierConfigManager.class).getConfigForSubId(subId); + return carrierConfig == null + ? false + : carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL); } /** @@ -396,14 +380,21 @@ public class MobileNetworkUtils { //TODO(b/117651939): move it to telephony private static boolean isTdscdmaSupported(Context context, TelephonyManager telephonyManager) { - if (context.getResources().getBoolean(R.bool.config_support_tdscdma)) { + final PersistableBundle carrierConfig = context.getSystemService( + CarrierConfigManager.class).getConfig(); + + if (carrierConfig == null) { + return false; + } + + if (carrierConfig.getBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL)) { return true; } String operatorNumeric = telephonyManager.getServiceState().getOperatorNumeric(); - String[] numericArray = context.getResources().getStringArray( - R.array.config_support_tdscdma_roaming_on_networks); - if (numericArray.length == 0 || operatorNumeric == null) { + String[] numericArray = carrierConfig.getStringArray( + CarrierConfigManager.KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY); + if (numericArray == null || operatorNumeric == null) { return false; } for (String numeric : numericArray) { @@ -413,4 +404,4 @@ public class MobileNetworkUtils { } return false; } -} \ No newline at end of file +} diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java index 676c9f4f23d..8a57a0cc751 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java @@ -165,7 +165,8 @@ public class MobileNetworkUtilsTest { @Test public void isCdmaOptions_worldModeWithGsmWcdma_returnTrue() { when(mTelephonyManager.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM); - when(mContext.getString(R.string.config_world_mode)).thenReturn("true"); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true); + Settings.Global.putInt(mContext.getContentResolver(), android.provider.Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID_1, TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA); From be92eb0fa7e3642e2b803af6d5c8b79c1cd3b475 Mon Sep 17 00:00:00 2001 From: cosmohsieh Date: Wed, 7 Nov 2018 15:59:39 +0800 Subject: [PATCH 06/23] Implemen WiFi MAC randomization api for WiFi MAC randomization preference. Use WifiConfiguration.macRandomizationSetting to get/set config. Bug: 117957974 Test: RunSettingsRoboTests Change-Id: I33f3f0003159b86e44e25e041ed5e41c58add6bd --- .../wifi/details/WifiPrivacyPreferenceController.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java index 2afe35bf2d4..9f81431829c 100644 --- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java +++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java @@ -67,7 +67,7 @@ public class WifiPrivacyPreferenceController extends BasePreferenceController im @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (mWifiConfiguration != null) { - //TODO(b/117957974): update MAC randomization level to WifiManager + mWifiConfiguration.macRandomizationSetting = Integer.parseInt((String) newValue); mWifiManager.updateNetwork(mWifiConfiguration); } updateSummary((DropDownPreference) preference, Integer.parseInt((String) newValue)); @@ -77,10 +77,9 @@ public class WifiPrivacyPreferenceController extends BasePreferenceController im @VisibleForTesting int getRandomizationValue() { if (mWifiConfiguration != null) { - //TODO(b/117957974): get real MAC randomization level from WifiManager - return 0; + return mWifiConfiguration.macRandomizationSetting; } - return 0; + return WifiConfiguration.RANDOMIZATION_PERSISTENT; } private void updateSummary(DropDownPreference preference, int macRandomized) { From 992b5038a19839ba4c38855535bb9d10d3aac03b Mon Sep 17 00:00:00 2001 From: Edgar Wang Date: Thu, 8 Nov 2018 00:56:21 +0800 Subject: [PATCH 07/23] Move "About Phone" to bottom of Settings main IA, above "Tips & Support" Bug: 118168552 Test: robotests Change-Id: I0a0f03bdb27d9eea48eb758496eefeebcbc57b6c --- AndroidManifest.xml | 6 +-- color-check-baseline.xml | 60 +++++++++++++++++++++++------- res/drawable/ic_homepage_about.xml | 36 ++++++++++++++++++ res/drawable/ic_phone_info.xml | 9 +++++ res/values/colors.xml | 7 ++-- 5 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 res/drawable/ic_homepage_about.xml create mode 100644 res/drawable/ic_phone_info.xml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index efa57ded87d..998040606a7 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -911,7 +911,7 @@ @@ -925,9 +925,9 @@ - + + android:value="com.android.settings.category.ia.homepage" /> + + + + @@ -1257,7 +1273,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1273,7 +1289,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1289,7 +1305,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1305,7 +1321,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1321,7 +1337,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1337,7 +1353,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1353,7 +1369,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1369,7 +1385,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1385,7 +1401,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1401,7 +1417,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1693,6 +1709,22 @@ column="9"/> + + + + + + + + + + + + + + + + + diff --git a/res/drawable/ic_phone_info.xml b/res/drawable/ic_phone_info.xml new file mode 100644 index 00000000000..7aee3e86ebc --- /dev/null +++ b/res/drawable/ic_phone_info.xml @@ -0,0 +1,9 @@ + + + diff --git a/res/values/colors.xml b/res/values/colors.xml index a00fd8a8b1f..11c1aaf4437 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -113,19 +113,20 @@ #2196F3 - #71A234 + #72B70F #FF7E0F #258982 - #FFB600 + #FFA727 #01B1AF #C14CE6 #0F9D58 #F15B8D #5011C1 - #757575 + #9E9E9E #26459C #1A73E8 #2EC7DC + #9FA8DA @*android:color/material_red_A700 From 2a98c843e8cb2bb43035bb2980e07bdb1ffeec92 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Mon, 5 Nov 2018 15:40:32 -0800 Subject: [PATCH 08/23] Loading suggestions via legacy SuggestionService sometimes When legacy_suggestion flag is turned on, load Suggestions from SuggestionService instead of contextual homepage, because contextual homepage infrastructure might not be availble on all devices. Bug: 118842099 Test: robo Change-Id: I91710c005e11be5a9b3dd39ceff670106e7f80c3 --- res/layout/homepage_condition_full_tile.xml | 4 +- res/layout/homepage_condition_half_tile.xml | 4 +- res/layout/homepage_suggestion_tile.xml | 70 ++++++++ res/values/config.xml | 6 + res/values/dimens.xml | 12 +- res/values/styles.xml | 12 +- .../contextualcards/ContextualCard.java | 4 +- .../ContextualCardLookupTable.java | 12 +- .../ContextualCardManager.java | 13 +- .../ContextualCardRenderer.java | 2 + .../ContextualCardUpdateListener.java | 3 + .../ControllerRendererPool.java | 11 +- .../ConditionContextualCardRenderer.java | 3 + .../LegacySuggestionContextualCard.java | 61 +++++++ ...acySuggestionContextualCardController.java | 156 ++++++++++++++++++ ...egacySuggestionContextualCardRenderer.java | 81 +++++++++ tests/robotests/res/values-mcc999/config.xml | 1 + .../ConditionalContextualCardTest.java | 2 +- ...uggestionContextualCardControllerTest.java | 94 +++++++++++ ...ySuggestionContextualCardRendererTest.java | 105 ++++++++++++ .../LegacySuggestionContextualCardTest.java | 55 ++++++ 21 files changed, 675 insertions(+), 36 deletions(-) create mode 100644 res/layout/homepage_suggestion_tile.xml create mode 100644 src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCard.java create mode 100644 src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardController.java create mode 100644 src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRenderer.java create mode 100644 tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardRendererTest.java create mode 100644 tests/robotests/src/com/android/settings/homepage/contextualcards/legacysuggestion/LegacySuggestionContextualCardTest.java diff --git a/res/layout/homepage_condition_full_tile.xml b/res/layout/homepage_condition_full_tile.xml index f00132b8507..1b68e760702 100644 --- a/res/layout/homepage_condition_full_tile.xml +++ b/res/layout/homepage_condition_full_tile.xml @@ -32,8 +32,8 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values/config.xml b/res/values/config.xml index b496080ea68..c357207d80c 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -134,6 +134,12 @@ have distinct intensity levels --> false + + true + true diff --git a/res/values/dimens.xml b/res/values/dimens.xml index c91ffb5f3b7..8432fe191df 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -303,17 +303,6 @@ 5dp 36dp - - 24dp - 14dp - 12dp - 16dp - 2dp - 12dp - 8dp - 16dp - 18dp - 2dp @@ -331,6 +320,7 @@ 68dp + 24dp 8dp 2dp 4dp diff --git a/res/values/styles.xml b/res/values/styles.xml index 70d8a93af1f..0e29b62c283 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -350,16 +350,8 @@ - -