Merge "New mechanism to enable ventors to present Google legal items dynamically." into pi-car-dev
am: 5a599c6663

Change-Id: I4e9ba65f1cd2f3f3bac8ab765917475ee17a6601
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0d17287..a4fed8d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -259,8 +259,13 @@
         </activity>
 
         <activity android:name=".system.ThirdPartyLicensesActivity"
+                  android:label="@string/settings_license_activity_title"
                   android:configChanges="orientation|keyboardHidden|screenSize"
                   android:windowSoftInputMode="adjustResize">
+            <intent-filter>
+                <action android:name="android.settings.THIRD_PARTY_LICENSE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
         </activity>
 
         <!-- This logic is copied from phone.-->
diff --git a/res/xml/legal_information_fragment.xml b/res/xml/legal_information_fragment.xml
index 5e1541a..e7e343f 100644
--- a/res/xml/legal_information_fragment.xml
+++ b/res/xml/legal_information_fragment.xml
@@ -19,18 +19,22 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/legal_information">
+
+    <!-- Terms and conditions -->
+    <Preference
+        android:key="terms"
+        android:title="@string/terms_title"
+        settings:controller="com.android.car.settings.system.legal.TermsPreferenceController"/>
+
+    <!-- System WebView License information -->
     <Preference
         android:key="@string/pk_system_license_entry"
         android:title="@string/webview_license_title"
-        settings:controller="com.android.car.settings.common.DefaultRestrictionsPreferenceController">
-        <intent android:action="android.settings.WEBVIEW_LICENSE"/>
-    </Preference>
+        settings:controller="com.android.car.settings.system.legal.WebViewLicensePreferenceController"/>
+
     <Preference
         android:key="@string/pk_third_party_license_entry"
         android:title="@string/settings_license_activity_title"
-        settings:controller="com.android.car.settings.common.DefaultRestrictionsPreferenceController">
-        <intent
-            android:targetClass="com.android.car.settings.system.ThirdPartyLicensesActivity"
-            android:targetPackage="com.android.car.settings"/>
-    </Preference>
+        settings:controller="com.android.car.settings.system.legal.ThirdPartyLicensePreferenceController"/>
+
 </PreferenceScreen>
diff --git a/src/com/android/car/settings/system/legal/LegalPreferenceController.java b/src/com/android/car/settings/system/legal/LegalPreferenceController.java
new file mode 100644
index 0000000..d05c852
--- /dev/null
+++ b/src/com/android/car/settings/system/legal/LegalPreferenceController.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 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.car.settings.system.legal;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+import androidx.preference.Preference;
+
+import com.android.car.settings.common.FragmentController;
+import com.android.car.settings.common.PreferenceController;
+
+import java.util.List;
+
+/**
+ *  Base class for legal preferences. Locates an activity coupled with the given intent and updates
+ *  the preference accordingly.
+ */
+public abstract class LegalPreferenceController extends PreferenceController<Preference> {
+    private final PackageManager mPackageManager;
+    private ResolveInfo mResolveInfo;
+
+    public LegalPreferenceController(Context context, String preferenceKey,
+            FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
+        super(context, preferenceKey, fragmentController, uxRestrictions);
+        mPackageManager = context.getPackageManager();
+    }
+
+    @Override
+    protected Class<Preference> getPreferenceType() {
+        return Preference.class;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        mResolveInfo = findMatchingSpecificActivity();
+        return mResolveInfo != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    protected void updateState(Preference preference) {
+        if (mResolveInfo == null) {
+            return;
+        }
+
+        // Replace the intent with this specific activity.
+        preference.setIntent(new Intent().setClassName(
+                mResolveInfo.activityInfo.packageName,
+                mResolveInfo.activityInfo.name));
+
+        preference.setTitle(mResolveInfo.loadLabel(mPackageManager));
+    }
+
+    /** Intent with a matching system activity to display legal disclaimers or licenses. */
+    protected abstract Intent getIntent();
+
+    private ResolveInfo findMatchingSpecificActivity() {
+        Intent intent = getIntent();
+        if (intent == null) {
+            return null;
+        }
+
+        // Find the activity that is in the system image.
+        List<ResolveInfo> list = mPackageManager.queryIntentActivities(intent, /* flags= */ 0);
+        if (list == null) {
+            return null;
+        }
+
+        for (ResolveInfo resolveInfo : list) {
+            if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
+                    != 0) {
+                return resolveInfo;
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/car/settings/system/legal/TermsPreferenceController.java b/src/com/android/car/settings/system/legal/TermsPreferenceController.java
new file mode 100644
index 0000000..5381a64
--- /dev/null
+++ b/src/com/android/car/settings/system/legal/TermsPreferenceController.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 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.car.settings.system.legal;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.car.settings.common.FragmentController;
+
+/** Links to a system activity that displays Terms and Conditions. */
+public class TermsPreferenceController extends LegalPreferenceController {
+    private static final Intent INTENT = new Intent("android.settings.TERMS");
+
+    public TermsPreferenceController(Context context, String preferenceKey,
+            FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
+        super(context, preferenceKey, fragmentController, uxRestrictions);
+    }
+
+    @Override
+    protected Intent getIntent() {
+        return INTENT;
+    }
+}
diff --git a/src/com/android/car/settings/system/legal/ThirdPartyLicensePreferenceController.java b/src/com/android/car/settings/system/legal/ThirdPartyLicensePreferenceController.java
new file mode 100644
index 0000000..c239bc9
--- /dev/null
+++ b/src/com/android/car/settings/system/legal/ThirdPartyLicensePreferenceController.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 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.car.settings.system.legal;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.car.settings.common.FragmentController;
+
+/** Links to a system activity that displays a list of third party licenses. */
+public class ThirdPartyLicensePreferenceController extends LegalPreferenceController {
+    private static final Intent INTENT = new Intent("android.settings.THIRD_PARTY_LICENSE");
+
+    public ThirdPartyLicensePreferenceController(Context context, String preferenceKey,
+            FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
+        super(context, preferenceKey, fragmentController, uxRestrictions);
+    }
+
+    @Override
+    protected Intent getIntent() {
+        return INTENT;
+    }
+}
diff --git a/src/com/android/car/settings/system/legal/WebViewLicensePreferenceController.java b/src/com/android/car/settings/system/legal/WebViewLicensePreferenceController.java
new file mode 100644
index 0000000..e25f7c2
--- /dev/null
+++ b/src/com/android/car/settings/system/legal/WebViewLicensePreferenceController.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 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.car.settings.system.legal;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.car.settings.common.FragmentController;
+
+/** Links to a system activity that displays System Webview Licenses. */
+public class WebViewLicensePreferenceController extends LegalPreferenceController {
+    private static final Intent INTENT = new Intent("android.settings.WEBVIEW_LICENSE");
+
+    public WebViewLicensePreferenceController(Context context, String preferenceKey,
+            FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
+        super(context, preferenceKey, fragmentController, uxRestrictions);
+    }
+
+    @Override
+    protected Intent getIntent() {
+        return INTENT;
+    }
+}
diff --git a/tests/robotests/src/com/android/car/settings/system/legal/LegalPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/system/legal/LegalPreferenceControllerTest.java
new file mode 100644
index 0000000..a01e6ef
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/system/legal/LegalPreferenceControllerTest.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2019 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.car.settings.system.legal;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.preference.Preference;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.common.FragmentController;
+import com.android.car.settings.common.PreferenceControllerTestHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowPackageManager;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/** Unit test for {@link LegalPreferenceController}. */
+@RunWith(CarSettingsRobolectricTestRunner.class)
+public class LegalPreferenceControllerTest {
+    private static class TestLegalPreferenceControllerTest extends
+            LegalPreferenceController {
+
+        private static final Intent INTENT = new Intent("test_intent");
+
+        TestLegalPreferenceControllerTest(Context context, String preferenceKey,
+                FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
+            super(context, preferenceKey, fragmentController, uxRestrictions);
+        }
+
+        @Override
+        protected Intent getIntent() {
+            return INTENT;
+        }
+    }
+
+    private static final String TEST_LABEL = "test_label";
+    private Context mContext;
+    private PreferenceControllerTestHelper<TestLegalPreferenceControllerTest> mControllerHelper;
+    private Preference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mPreference = new Preference(mContext);
+        mControllerHelper = new PreferenceControllerTestHelper<>(mContext,
+                TestLegalPreferenceControllerTest.class, mPreference);
+    }
+
+    @Test
+    public void refreshUi_intentResolvesToActivity_isVisible() {
+        Intent intent = mControllerHelper.getController().getIntent();
+
+        ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.packageName = "some.test.package";
+        activityInfo.name = "SomeActivity";
+        activityInfo.applicationInfo = new ApplicationInfo();
+        activityInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+
+        ResolveInfo resolveInfo = new ResolveInfo() {
+            @Override
+            public CharSequence loadLabel(PackageManager pm) {
+                return TEST_LABEL;
+            }
+        };
+        resolveInfo.activityInfo = activityInfo;
+        List<ResolveInfo> list = new LinkedList();
+        list.add(resolveInfo);
+
+        ShadowPackageManager packageManager = Shadows.shadowOf(mContext.getPackageManager());
+        packageManager.addResolveInfoForIntent(intent, list);
+
+        mControllerHelper.markState(Lifecycle.State.CREATED);
+        mControllerHelper.getController().refreshUi();
+
+        assertThat(mPreference.isVisible()).isTrue();
+    }
+
+    @Test
+    public void refreshUi_intentResolvesToActivity_updatesTitle() {
+        Intent intent = mControllerHelper.getController().getIntent();
+
+        ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.packageName = "some.test.package";
+        activityInfo.name = "SomeActivity";
+        activityInfo.applicationInfo = new ApplicationInfo();
+        activityInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+
+        ResolveInfo resolveInfo = new ResolveInfo() {
+            @Override
+            public CharSequence loadLabel(PackageManager pm) {
+                return TEST_LABEL;
+            }
+        };
+        resolveInfo.activityInfo = activityInfo;
+        List<ResolveInfo> list = new LinkedList();
+        list.add(resolveInfo);
+
+        ShadowPackageManager packageManager = Shadows.shadowOf(mContext.getPackageManager());
+        packageManager.addResolveInfoForIntent(intent, list);
+
+        mControllerHelper.markState(Lifecycle.State.CREATED);
+        mControllerHelper.getController().refreshUi();
+
+        assertThat(mPreference.getTitle()).isEqualTo(TEST_LABEL);
+    }
+
+    @Test
+    public void refreshUi_intentResolvesToActivity_updatesIntentToSpecificActivity() {
+        Intent intent = mControllerHelper.getController().getIntent();
+
+        String packageName = "com.android.car.settings.testutils";
+        String activityName = "BaseTestActivity";
+
+        ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.packageName = packageName;
+        activityInfo.name = activityName;
+        activityInfo.applicationInfo = new ApplicationInfo();
+        activityInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+
+        ResolveInfo resolveInfo = new ResolveInfo() {
+            @Override
+            public CharSequence loadLabel(PackageManager pm) {
+                return TEST_LABEL;
+            }
+        };
+        resolveInfo.activityInfo = activityInfo;
+        List<ResolveInfo> list = new LinkedList();
+        list.add(resolveInfo);
+
+        ShadowPackageManager packageManager = Shadows.shadowOf(mContext.getPackageManager());
+        packageManager.addResolveInfoForIntent(intent, list);
+
+        mControllerHelper.markState(Lifecycle.State.CREATED);
+        mControllerHelper.getController().refreshUi();
+
+        assertThat(mPreference.getIntent().getComponent().flattenToString()).isEqualTo(
+                packageName + "/" + activityName);
+    }
+
+    @Test
+    public void refreshUi_intentResolvesToNull_isNotVisible() {
+        ShadowPackageManager packageManager = Shadows.shadowOf(mContext.getPackageManager());
+
+        packageManager.addResolveInfoForIntent(mControllerHelper.getController().getIntent(),
+                Collections.emptyList());
+
+        mControllerHelper.markState(Lifecycle.State.CREATED);
+        mControllerHelper.getController().refreshUi();
+
+        assertThat(mPreference.isVisible()).isFalse();
+    }
+}