Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2273bbde authored by Hai Zhang's avatar Hai Zhang
Browse files

Resolve all browsers even if there is a default browser.

PackageManager.queryIntentActivities() handles browser intent
differently when there is a default browser, and only returns the
default browser. Previous code for querying all the browsers all
passed in the PackageManager.MATCH_ALL flag and filtered the result
manually, so we move that logic into RoleBehavior.

Bug: 110557011
Test: build
Change-Id: I7de15113e21aacec2bf20ef98b8fa01fd2580564
parent 5ed12fc3
Loading
Loading
Loading
Loading
+14 −14
Original line number Original line Diff line number Diff line
@@ -543,28 +543,28 @@


    <!-- TODO: STOPSHIP: Migrate all default app titles from packages/apps/Settings/res/values/strings.xml . -->
    <!-- TODO: STOPSHIP: Migrate all default app titles from packages/apps/Settings/res/values/strings.xml . -->


    <!-- Label for the browser role. [CHAR LIMIT=30] -->
    <string name="role_label_browser">Browser app</string>
    <!-- Label for the dialer role. [CHAR LIMIT=30] -->
    <!-- Label for the dialer role. [CHAR LIMIT=30] -->
    <string name="role_label_dialer">Phone app</string>
    <string name="role_label_dialer">Phone app</string>
    <!-- Label for the SMS role. [CHAR LIMIT=30] -->
    <string name="role_label_sms">SMS app</string>
    <!-- Label for the emergency role. [CHAR LIMIT=30] -->
    <string name="role_label_emergency">Emergency app</string>
    <!-- Label for the home role. [CHAR LIMIT=30] -->
    <string name="role_label_home">Home app</string>
    <!-- Label for the music player role. [CHAR LIMIT=30] -->
    <string name="role_label_music">Music app</string>
    <!-- Label for the gallery role. [CHAR LIMIT=30] -->
    <string name="role_label_gallery">Gallery app</string>
    <!-- Label for the automotive dialer role. [CHAR LIMIT=30] -->
    <!-- Label for the automotive dialer role. [CHAR LIMIT=30] -->
    <string name="role_label_car_mode_dialer">Car mode phone app</string>
    <string name="role_label_car_mode_dialer">Car mode phone app</string>
    <!-- Label for the proxy calling app role. [CHAR LIMIT=30] -->
    <string name="role_label_proxy_calling">Proxy calling app</string>
    <!-- Label for the call screening role. [CHAR LIMIT=30] -->
    <!-- Label for the call screening role. [CHAR LIMIT=30] -->
    <string name="role_label_call_screening">Call screening app</string>
    <string name="role_label_call_screening">Call screening app</string>
    <!-- Label for the call companion app role. [CHAR LIMIT=30] -->
    <!-- Label for the call companion app role. [CHAR LIMIT=30] -->
    <string name="role_label_call_companion">Call companion app</string>
    <string name="role_label_call_companion">Call companion app</string>
    <!-- Label for the proxy calling app role. [CHAR LIMIT=30] -->
    <string name="role_label_proxy_calling">Proxy calling app</string>
    <!-- Label for the SMS role. [CHAR LIMIT=30] -->
    <string name="role_label_sms">SMS app</string>
    <!-- Label for the browser role. [CHAR LIMIT=30] -->
    <string name="role_label_browser">Browser app</string>
    <!-- Label for the gallery role. [CHAR LIMIT=30] -->
    <string name="role_label_gallery">Gallery app</string>
    <!-- Label for the music player role. [CHAR LIMIT=30] -->
    <string name="role_label_music">Music app</string>
    <!-- Label for the home role. [CHAR LIMIT=30] -->
    <string name="role_label_home">Home app</string>
    <!-- Label for the emergency role. [CHAR LIMIT=30] -->
    <string name="role_label_emergency">Emergency app</string>


    <!-- Dialog body explaining that the app just selected by the user will not work after a reboot until the user enters their credentials, such as a PIN or password. [CHAR LIMIT=NONE] -->
    <!-- Dialog body explaining that the app just selected by the user will not work after a reboot until the user enters their credentials, such as a PIN or password. [CHAR LIMIT=NONE] -->
    <string name="encryption_unaware_confirmation_message">Note: If you restart your device and have a screen lock set, this app can\u2019t start until you unlock your device.</string>
    <string name="encryption_unaware_confirmation_message">Note: If you restart your device and have a screen lock set, this app can\u2019t start until you unlock your device.</string>
+67 −60
Original line number Original line Diff line number Diff line
@@ -77,6 +77,36 @@
        <permission name="android.permission.READ_MEDIA_IMAGES" />
        <permission name="android.permission.READ_MEDIA_IMAGES" />
    </permission-set>
    </permission-set>


    <!---
      ~ @see com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController
      ~ @see com.android.settings.applications.defaultapps.DefaultBrowserPicker
      ~ @see com.android.server.pm.PackageManagerService.resolveAllBrowserApps(int)
      ~ @see com.android.server.pm.PackageManagerService.setDefaultBrowserPackageName(String, int)
      ~ @see com.android.server.pm.permission.DefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultBrowser(String, int)
      -->
    <role name="android.app.role.BROWSER" exclusive="true" label="@string/role_label_browser">
        <!--
          ~ Required components matching is handled in BrowserRoleBehavior because it needs the
          ~ PackageManager.MATCH_ALL flag and other manual filtering, which cannot fit in our
          ~ current mechanism easily.
          -->
        <!--
        <required-components>
            <activity>
                <intent-filter>
                    <action name="android.intent.action.VIEW" />
                    <category name="android.intent.category.BROWSABLE" />
                    <data scheme="http" />
                </intent-filter>
            </activity>
        </required-components>
        -->
        <!--
          ~ Not need to set preferred activity because PackageManager handles browser intents
          ~ specially.
          -->
    </role>

    <!--
    <!--
      ~ @see com.android.settings.applications.defaultapps.DefaultPhonePreferenceController
      ~ @see com.android.settings.applications.defaultapps.DefaultPhonePreferenceController
      ~ @see com.android.settings.applications.defaultapps.DefaultPhonePicker
      ~ @see com.android.settings.applications.defaultapps.DefaultPhonePicker
@@ -226,143 +256,120 @@
        </preferred-activities>
        </preferred-activities>
    </role>
    </role>


    <!-- TODO: STOPSHIP: Add availability and confirmation message in role behavior. -->
    <!-- TODO: STOPSHIP: Intent action sometimes changing dynamically in com.android.phone.EmergencyAssistanceHelper.getIntentAction -->
    <!-- TODO: STOPSHIP: Make this non-configurable at least by default. -->
    <!-- TODO: STOPSHIP: Make sure we initialize an emergency app for user. -->
    <!---
    <!---
      ~ @see com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController
      ~ @see com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController
      ~ @see com.android.settings.applications.defaultapps.DefaultBrowserPicker
      ~ @see com.android.settings.applications.defaultapps.DefaultEmergencyPicker
      ~ @see com.android.server.pm.PackageManagerService.setDefaultBrowserPackageName(String, int)
      ~ @see com.android.phone.EmergencyAssistanceHelper
      ~ @see com.android.server.pm.permission.DefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultBrowser(String, int)
      -->
      -->
    <role name="android.app.role.BROWSER" exclusive="true" label="@string/role_label_browser">
    <role name="android.app.role.EMERGENCY" exclusive="true" label="@string/role_label_emergency">
        <required-components>
        <required-components>
            <activity>
            <activity>
                <intent-filter>
                <intent-filter>
                    <action name="android.intent.action.VIEW" />
                    <action name="android.telephony.action.EMERGENCY_ASSISTANCE" />
                    <category name="android.intent.category.BROWSABLE" />
                    <data scheme="http" />
                </intent-filter>
                </intent-filter>
            </activity>
            </activity>
        </required-components>
        </required-components>
        <permissions>
            <!-- FIXME: STOPSHIP: This should only be granted to system app? -->
            <permission-set name="location" />
        </permissions>
        <!-- TODO: STOPSHIP: Set preferred? -->
    </role>
    </role>


    <role name="android.app.role.MUSIC" exclusive="true" label="@string/role_label_music">
    <!-- TODO: STOPSHIP: Add availability in role behavior. -->
    <!-- TODO: STOPSHIP: Filter qualifiying apps according to work profile support as in com.android.settings.applications.defaultapps.DefaultHomePicker.getCandidates() -->
    <!---
      ~ @see com.android.settings.applications.defaultapps.DefaultHomePreferenceController
      ~ @see com.android.settings.applications.defaultapps.DefaultHomePicker
      ~ @see com.android.server.pm.PackageManagerService#setHomeActivity(ComponentName, int)
      -->
    <role name="android.app.role.HOME" exclusive="true" label="@string/role_label_home">
        <required-components>
        <required-components>
            <activity>
            <activity>
                <intent-filter>
                <intent-filter>
                    <action name="android.intent.action.MAIN" />
                    <action name="android.intent.action.MAIN" />
                    <category name="android.intent.category.APP_MUSIC" />
                    <category name="android.intent.category.HOME" />
                </intent-filter>
                </intent-filter>
            </activity>
            </activity>
        </required-components>
        </required-components>
        <permissions>
            <permission-set name="media_aural" />
        </permissions>
        <app-ops>
            <app-op name="android:write_media_audio" mode="allowed" />
        </app-ops>
        <preferred-activities>
        <preferred-activities>
            <preferred-activity>
            <preferred-activity>
                <activity>
                <activity>
                    <intent-filter>
                    <intent-filter>
                        <action name="android.intent.action.MAIN" />
                        <action name="android.intent.action.MAIN" />
                        <category name="android.intent.category.APP_MUSIC" />
                        <category name="android.intent.category.HOME" />
                    </intent-filter>
                    </intent-filter>
                </activity>
                </activity>
                <intent-filter>
                <intent-filter>
                    <action name="android.intent.action.MAIN" />
                    <action name="android.intent.action.MAIN" />
                    <category name="android.intent.category.APP_MUSIC" />
                    <category name="android.intent.category.HOME" />
                </intent-filter>
                </intent-filter>
            </preferred-activity>
            </preferred-activity>
        </preferred-activities>
        </preferred-activities>
    </role>
    </role>


    <role name="android.app.role.GALLERY" exclusive="true" label="@string/role_label_gallery">
    <role name="android.app.role.MUSIC" exclusive="true" label="@string/role_label_music">
        <required-components>
        <required-components>
            <activity>
            <activity>
                <intent-filter>
                <intent-filter>
                    <action name="android.intent.action.MAIN" />
                    <action name="android.intent.action.MAIN" />
                    <category name="android.intent.category.APP_GALLERY" />
                    <category name="android.intent.category.APP_MUSIC" />
                </intent-filter>
                </intent-filter>
            </activity>
            </activity>
        </required-components>
        </required-components>
        <permissions>
        <permissions>
            <permission-set name="media_visual" />
            <permission-set name="media_aural" />
        </permissions>
        </permissions>
        <app-ops>
        <app-ops>
            <app-op name="android:write_media_video" mode="allowed" />
            <app-op name="android:write_media_audio" mode="allowed" />
            <app-op name="android:write_media_images" mode="allowed" />
        </app-ops>
        </app-ops>
        <preferred-activities>
        <preferred-activities>
            <preferred-activity>
            <preferred-activity>
                <activity>
                <activity>
                    <intent-filter>
                    <intent-filter>
                        <action name="android.intent.action.MAIN" />
                        <action name="android.intent.action.MAIN" />
                        <category name="android.intent.category.APP_GALLERY" />
                        <category name="android.intent.category.APP_MUSIC" />
                    </intent-filter>
                    </intent-filter>
                </activity>
                </activity>
                <intent-filter>
                <intent-filter>
                    <action name="android.intent.action.MAIN" />
                    <action name="android.intent.action.MAIN" />
                    <category name="android.intent.category.APP_GALLERY" />
                    <category name="android.intent.category.APP_MUSIC" />
                </intent-filter>
                </intent-filter>
            </preferred-activity>
            </preferred-activity>
        </preferred-activities>
        </preferred-activities>
    </role>
    </role>


    <!-- TODO: STOPSHIP: Add availability in role behavior. -->
    <role name="android.app.role.GALLERY" exclusive="true" label="@string/role_label_gallery">
    <!-- TODO: STOPSHIP: Filter qualifiying apps according to work profile support as in com.android.settings.applications.defaultapps.DefaultHomePicker.getCandidates() -->
    <!---
      ~ @see com.android.settings.applications.defaultapps.DefaultHomePreferenceController
      ~ @see com.android.settings.applications.defaultapps.DefaultHomePicker
      ~ @see com.android.server.pm.PackageManagerService#setHomeActivity(ComponentName, int)
      -->
    <role name="android.app.role.HOME" exclusive="true" label="@string/role_label_home">
        <required-components>
        <required-components>
            <activity>
            <activity>
                <intent-filter>
                <intent-filter>
                    <action name="android.intent.action.MAIN" />
                    <action name="android.intent.action.MAIN" />
                    <category name="android.intent.category.HOME" />
                    <category name="android.intent.category.APP_GALLERY" />
                </intent-filter>
                </intent-filter>
            </activity>
            </activity>
        </required-components>
        </required-components>
        <permissions>
            <permission-set name="media_visual" />
        </permissions>
        <app-ops>
            <app-op name="android:write_media_video" mode="allowed" />
            <app-op name="android:write_media_images" mode="allowed" />
        </app-ops>
        <preferred-activities>
        <preferred-activities>
            <preferred-activity>
            <preferred-activity>
                <activity>
                <activity>
                    <intent-filter>
                    <intent-filter>
                        <action name="android.intent.action.MAIN" />
                        <action name="android.intent.action.MAIN" />
                        <category name="android.intent.category.HOME" />
                        <category name="android.intent.category.APP_GALLERY" />
                    </intent-filter>
                    </intent-filter>
                </activity>
                </activity>
                <intent-filter>
                <intent-filter>
                    <action name="android.intent.action.MAIN" />
                    <action name="android.intent.action.MAIN" />
                    <category name="android.intent.category.HOME" />
                    <category name="android.intent.category.APP_GALLERY" />
                </intent-filter>
                </intent-filter>
            </preferred-activity>
            </preferred-activity>
        </preferred-activities>
        </preferred-activities>
    </role>
    </role>


    <!-- TODO: STOPSHIP: Add availability and confirmation message in role behavior. -->
    <!-- TODO: STOPSHIP: Intent action sometimes changing dynamically in com.android.phone.EmergencyAssistanceHelper.getIntentAction -->
    <!-- TODO: STOPSHIP: Make this non-configurable at least by default. -->
    <!-- TODO: STOPSHIP: Make sure we initialize an emergency app for user. -->
    <!---
      ~ @see com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController
      ~ @see com.android.settings.applications.defaultapps.DefaultEmergencyPicker
      ~ @see com.android.phone.EmergencyAssistanceHelper
      -->
    <role name="android.app.role.EMERGENCY" exclusive="true" label="@string/role_label_emergency">
        <required-components>
            <activity>
                <intent-filter>
                    <action name="android.telephony.action.EMERGENCY_ASSISTANCE" />
                </intent-filter>
            </activity>
        </required-components>
    </role>

    <!--- @see android.telecom.InCallService -->
    <!--- @see android.telecom.InCallService -->
    <role
    <role
        name="android.app.role.CAR_MODE_DIALER_APP"
        name="android.app.role.CAR_MODE_DIALER_APP"
+92 −0
Original line number Original line Diff line number Diff line
/*
 * 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.packageinstaller.role.model;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Process;
import android.os.UserHandle;
import android.util.ArraySet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

/**
 * Class for behavior of the dialer role.
 *
 * @see com.android.settings.applications.DefaultAppSettings
 * @see com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController
 * @see com.android.settings.applications.defaultapps.DefaultBrowserPicker
 * @see com.android.server.pm.PackageManagerService#resolveAllBrowserApps(int)
 */
public class BrowserRoleBehavior implements RoleBehavior {

    private static final Intent BROWSER_INTENT = new Intent()
            .setAction(Intent.ACTION_VIEW)
            .addCategory(Intent.CATEGORY_BROWSABLE)
            .setData(Uri.fromParts("http", "", null));

    // PackageManager.queryIntentActivities() will only return the default browser if one was set.
    // Code in the Settings app passes PackageManager.MATCH_ALL and perform its own filtering, so we
    // do the same thing here.
    @Nullable
    @Override
    public List<String> getQualifyingPackagesAsUser(@NonNull Role role, @NonNull UserHandle user,
            @NonNull Context context) {
        return getQualifyingPackagesAsUserInternal(null, user, context);
    }

    @Nullable
    @Override
    public Boolean isPackageQualified(@NonNull Role role, @NonNull String packageName,
            @NonNull Context context) {
        List<String> packageNames = getQualifyingPackagesAsUserInternal(packageName,
                Process.myUserHandle(), context);
        return !packageNames.isEmpty();
    }

    @NonNull
    private List<String> getQualifyingPackagesAsUserInternal(@Nullable String packageName,
            @NonNull UserHandle user, @NonNull Context context) {
        PackageManager packageManager = context.getPackageManager();
        Intent intent = BROWSER_INTENT;
        if (packageName != null) {
            intent = new Intent(intent)
                    .setPackage(packageName);
        }
        List<ResolveInfo> resolveInfos = packageManager.queryIntentActivitiesAsUser(intent,
                PackageManager.MATCH_ALL, user);
        ArraySet<String> packageNames = new ArraySet<>();
        int resolveInfosSize = resolveInfos.size();
        for (int i = 0; i < resolveInfosSize; i++) {
            ResolveInfo resolveInfo = resolveInfos.get(i);

            if (!resolveInfo.handleAllWebDataURI || !resolveInfo.activityInfo.enabled
                    || !resolveInfo.activityInfo.applicationInfo.enabled) {
                continue;
            }
            packageNames.add(resolveInfo.activityInfo.packageName);
        }
        return new ArrayList<>(packageNames);
    }
}