Return app hidden details activity in launcher api
If a normal app does not have launcher icon, launcher api will return app details activity instead, so user will be noticed that the app is still installed. Bug: 111348460 Test: Installed an app without launcher activity, an app icon is being shown in launcher allapps, and it forwards user to app details page. Change-Id: I9c17f5edfdefe19727145e7176d7e113286c997d
This commit is contained in:
36
core/java/android/app/AppDetailsActivity.java
Normal file
36
core/java/android/app/AppDetailsActivity.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 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 android.app;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Helper activity that forwards you to app details page.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class AppDetailsActivity extends Activity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(android.net.Uri.fromParts("package", getPackageName(), null));
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package android.content.pm;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager.ApplicationInfoFlags;
|
||||
@@ -204,6 +205,29 @@ public abstract class PackageManagerInternal {
|
||||
public abstract PackageInfo getPackageInfo(String packageName,
|
||||
@PackageInfoFlags int flags, int filterCallingUid, int userId);
|
||||
|
||||
/**
|
||||
* Return a List of all application packages that are installed on the
|
||||
* device, for a specific user. If flag GET_UNINSTALLED_PACKAGES has been
|
||||
* set, a list of all applications including those deleted with
|
||||
* {@code DONT_DELETE_DATA} (partially installed apps with data directory)
|
||||
* will be returned.
|
||||
*
|
||||
* @param flags Additional option flags to modify the data returned.
|
||||
* @param userId The user for whom the installed applications are to be
|
||||
* listed
|
||||
* @param callingUid The uid of the original caller app
|
||||
* @return A List of ApplicationInfo objects, one for each installed
|
||||
* application. In the unlikely case there are no installed
|
||||
* packages, an empty list is returned. If flag
|
||||
* {@code MATCH_UNINSTALLED_PACKAGES} is set, the application
|
||||
* information is retrieved from the list of uninstalled
|
||||
* applications (which includes installed applications as well as
|
||||
* applications with data directory i.e. applications which had been
|
||||
* deleted with {@code DONT_DELETE_DATA} flag set).
|
||||
*/
|
||||
public abstract List<ApplicationInfo> getInstalledApplications(
|
||||
@ApplicationInfoFlags int flags, @UserIdInt int userId, int callingUid);
|
||||
|
||||
/**
|
||||
* Retrieve launcher extras for a suspended package provided to the system in
|
||||
* {@link PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
|
||||
|
||||
@@ -47,6 +47,7 @@ import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.AppDetailsActivity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
@@ -3876,6 +3877,11 @@ public class PackageParser {
|
||||
}
|
||||
}
|
||||
|
||||
// Add a hidden app detail activity which forwards user to App Details page.
|
||||
Activity a = generateAppDetailsHiddenActivity(owner, flags, outError,
|
||||
owner.baseHardwareAccelerated);
|
||||
owner.activities.add(a);
|
||||
|
||||
if (hasActivityOrder) {
|
||||
Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
|
||||
}
|
||||
@@ -4115,9 +4121,14 @@ public class PackageParser {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
outInfo.name
|
||||
String outInfoName
|
||||
= buildClassName(owner.applicationInfo.packageName, name, outError);
|
||||
if (outInfo.name == null) {
|
||||
if (AppDetailsActivity.class.getName().equals(outInfoName)) {
|
||||
outError[0] = tag + " invalid android:name";
|
||||
return false;
|
||||
}
|
||||
outInfo.name = outInfoName;
|
||||
if (outInfoName == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -4156,6 +4167,45 @@ public class PackageParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate activity object that forwards user to App Details page automatically.
|
||||
* This activity should be invisible to user and user should not know or see it.
|
||||
*/
|
||||
private @NonNull PackageParser.Activity generateAppDetailsHiddenActivity(
|
||||
PackageParser.Package owner, int flags, String[] outError,
|
||||
boolean hardwareAccelerated) {
|
||||
|
||||
// Build custom App Details activity info instead of parsing it from xml
|
||||
Activity a = new Activity(owner, AppDetailsActivity.class.getName(), new ActivityInfo());
|
||||
a.owner = owner;
|
||||
a.setPackageName(owner.packageName);
|
||||
|
||||
a.info.theme = 0;
|
||||
a.info.exported = true;
|
||||
a.info.name = AppDetailsActivity.class.getName();
|
||||
a.info.processName = owner.applicationInfo.processName;
|
||||
a.info.uiOptions = a.info.applicationInfo.uiOptions;
|
||||
a.info.taskAffinity = buildTaskAffinityName(owner.packageName, owner.packageName,
|
||||
":app_details", outError);
|
||||
a.info.enabled = true;
|
||||
a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
|
||||
a.info.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
|
||||
a.info.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
|
||||
a.info.configChanges = getActivityConfigChanges(0, 0);
|
||||
a.info.softInputMode = 0;
|
||||
a.info.persistableMode = ActivityInfo.PERSIST_NEVER;
|
||||
a.info.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
|
||||
a.info.lockTaskLaunchMode = 0;
|
||||
a.info.encryptionAware = a.info.directBootAware = false;
|
||||
a.info.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
|
||||
a.info.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
|
||||
if (hardwareAccelerated) {
|
||||
a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
private Activity parseActivity(Package owner, Resources res,
|
||||
XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
|
||||
boolean receiver, boolean hardwareAccelerated)
|
||||
@@ -7178,10 +7228,16 @@ public class PackageParser {
|
||||
ComponentName componentName;
|
||||
String componentShortName;
|
||||
|
||||
public Component(Package _owner) {
|
||||
owner = _owner;
|
||||
intents = null;
|
||||
className = null;
|
||||
public Component(Package owner, ArrayList<II> intents, String className) {
|
||||
this.owner = owner;
|
||||
this.intents = intents;
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public Component(Package owner) {
|
||||
this.owner = owner;
|
||||
this.intents = null;
|
||||
this.className = null;
|
||||
}
|
||||
|
||||
public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
|
||||
@@ -7646,6 +7702,13 @@ public class PackageParser {
|
||||
return mHasMaxAspectRatio;
|
||||
}
|
||||
|
||||
// To construct custom activity which does not exist in manifest
|
||||
Activity(final Package owner, final String className, final ActivityInfo info) {
|
||||
super(owner, new ArrayList<>(0), className);
|
||||
this.info = info;
|
||||
this.info.applicationInfo = owner.applicationInfo;
|
||||
}
|
||||
|
||||
public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
|
||||
super(args, _info);
|
||||
info = _info;
|
||||
|
||||
Reference in New Issue
Block a user