/* * Copyright (C) 2007 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 static android.app.WindowConfiguration.activityTypeToString; import static android.app.WindowConfiguration.windowingModeToString; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import android.Manifest; import android.annotation.ColorInt; import android.annotation.DrawableRes; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UserIdInt; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Icon; import android.hardware.HardwareBuffer; import android.os.BatteryStats; import android.os.Binder; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Debug; import android.os.Handler; import android.os.IBinder; import android.os.LocaleList; import android.os.Parcel; import android.os.Parcelable; import android.os.PowerExemptionManager; import android.os.PowerExemptionManager.ReasonCode; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; import android.text.TextUtils; import android.util.ArrayMap; import android.util.DisplayMetrics; import android.util.Singleton; import android.util.Size; import android.view.WindowInsetsController.Appearance; import android.window.TaskSnapshot; import com.android.internal.app.LocalePicker; import com.android.internal.app.procstats.ProcessStats; import com.android.internal.os.RoSystemProperties; import com.android.internal.os.TransferPipe; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.MemInfoReader; import com.android.internal.util.Preconditions; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; /** *
* This class gives information about, and interacts * with, activities, services, and the containing * process. *
* ** A number of the methods in this class are for * debugging or informational purposes and they should * not be used to affect any runtime behavior of * your app. These methods are called out as such in * the method level documentation. *
* ** Most application developers should not have the need to * use this class, most of whose methods are for specialized * use cases. However, a few methods are more broadly applicable. * For instance, {@link android.app.ActivityManager#isLowRamDevice() isLowRamDevice()} * enables your app to detect whether it is running on a low-memory device, * and behave accordingly. * {@link android.app.ActivityManager#clearApplicationUserData() clearApplicationUserData()} * is for apps with reset-data functionality. *
* ** In some special use cases, where an app interacts with * its Task stack, the app may use the * {@link android.app.ActivityManager.AppTask} and * {@link android.app.ActivityManager.RecentTaskInfo} inner * classes. However, in general, the methods in this class should * be used for testing and debugging purposes only. *
*/ @SystemService(Context.ACTIVITY_SERVICE) @android.ravenwood.annotation.RavenwoodKeepPartialClass public class ActivityManager { private static String TAG = "ActivityManager"; @UnsupportedAppUsage private final Context mContext; private static volatile boolean sSystemReady = false; private static final int FIRST_START_FATAL_ERROR_CODE = -100; private static final int LAST_START_FATAL_ERROR_CODE = -1; private static final int FIRST_START_SUCCESS_CODE = 0; private static final int LAST_START_SUCCESS_CODE = 99; private static final int FIRST_START_NON_FATAL_ERROR_CODE = 100; private static final int LAST_START_NON_FATAL_ERROR_CODE = 199; /** * Disable hidden API checks for the newly started instrumentation. * @hide */ public static final int INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS = 1 << 0; /** * Grant full access to the external storage for the newly started instrumentation. * @hide */ public static final int INSTR_FLAG_DISABLE_ISOLATED_STORAGE = 1 << 1; /** * Disable test API access for the newly started instrumentation. * @hide */ public static final int INSTR_FLAG_DISABLE_TEST_API_CHECKS = 1 << 2; /** * Do not restart the target process when starting or finishing instrumentation. * @hide */ public static final int INSTR_FLAG_NO_RESTART = 1 << 3; /** * Force the check that instrumentation and the target package are signed with the same * certificate even if {@link Build#IS_DEBUGGABLE} is {@code true}. * @hide */ public static final int INSTR_FLAG_ALWAYS_CHECK_SIGNATURE = 1 << 4; /** * Instrument Sdk Sandbox process that corresponds to the target package. * @hide */ public static final int INSTR_FLAG_INSTRUMENT_SDK_SANDBOX = 1 << 5; /** * Instrument an Sdk Sandbox process corresponding to an Sdk running inside the sandbox. * @hide */ public static final int INSTR_FLAG_INSTRUMENT_SDK_IN_SANDBOX = 1 << 6; static final class MyUidObserver extends UidObserver { final OnUidImportanceListener mListener; final Context mContext; MyUidObserver(OnUidImportanceListener listener, Context clientContext) { mListener = listener; mContext = clientContext; } @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { mListener.onUidImportance(uid, RunningAppProcessInfo.procStateToImportanceForClient( procState, mContext)); } @Override public void onUidGone(int uid, boolean disabled) { mListener.onUidImportance(uid, RunningAppProcessInfo.IMPORTANCE_GONE); } } final ArrayMapIn the future, apps in {@link #RESTRICTION_LEVEL_EXEMPTED} would receive permissive * background restrictions to protect the system from buggy behaviors; in other words, * the {@link #RESTRICTION_LEVEL_EXEMPTED} would not be the truly "unrestricted" state, while * the {@link #RESTRICTION_LEVEL_UNRESTRICTED} here would be the last resort if there is * a strong reason to grant such a capability to a system app.
* * @hide */ public static final int RESTRICTION_LEVEL_UNRESTRICTED = 10; /** * The default background restriction level for the "unrestricted" apps set by the user, * where it'll have the {@link android.app.AppOpsManager#OP_RUN_ANY_IN_BACKGROUND} set to * ALLOWED, being added into the device idle allow list; however there will be still certain * restrictions to apps in this level. * * @hide */ public static final int RESTRICTION_LEVEL_EXEMPTED = 20; /** * The default background restriction level for all other apps, they'll be moved between * various standby buckets, including * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_ACTIVE}, * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_WORKING_SET}, * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_FREQUENT}, * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RARE}. * * @hide */ public static final int RESTRICTION_LEVEL_ADAPTIVE_BUCKET = 30; /** * The background restriction level where the apps will be placed in the restricted bucket * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED}. * * @hide */ public static final int RESTRICTION_LEVEL_RESTRICTED_BUCKET = 40; /** * The background restricted level, where apps would get more restrictions, * such as not allowed to launch foreground services besides on TOP. * * @hide */ public static final int RESTRICTION_LEVEL_BACKGROUND_RESTRICTED = 50; /** * The restricted level where the apps are in a force-stopped state. * * @hide */ public static final int RESTRICTION_LEVEL_FORCE_STOPPED = 60; /** * The heavily background restricted level, where apps cannot start without an explicit * launch by the user. * * @hide */ public static final int RESTRICTION_LEVEL_USER_LAUNCH_ONLY = 70; /** * A reserved restriction level that is not well-defined. * * @hide */ public static final int RESTRICTION_LEVEL_CUSTOM = 90; /** * Not a valid restriction level, it defines the maximum numerical value of restriction level. * * @hide */ public static final int RESTRICTION_LEVEL_MAX = 100; /** @hide */ @IntDef(prefix = { "RESTRICTION_LEVEL_" }, value = { RESTRICTION_LEVEL_UNKNOWN, RESTRICTION_LEVEL_UNRESTRICTED, RESTRICTION_LEVEL_EXEMPTED, RESTRICTION_LEVEL_ADAPTIVE_BUCKET, RESTRICTION_LEVEL_RESTRICTED_BUCKET, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, RESTRICTION_LEVEL_FORCE_STOPPED, RESTRICTION_LEVEL_USER_LAUNCH_ONLY, RESTRICTION_LEVEL_CUSTOM, RESTRICTION_LEVEL_MAX, }) @Retention(RetentionPolicy.SOURCE) public @interface RestrictionLevel{} /** * Maximum string length for sub reason for restriction. * * @hide */ public static final int RESTRICTION_SUBREASON_MAX_LENGTH = 16; /** * Restriction reason unknown - do not use directly. * * For use with noteAppRestrictionEnabled() * @hide */ public static final int RESTRICTION_REASON_UNKNOWN = 0; /** * Restriction reason to be used when this is normal behavior for the state. * * For use with noteAppRestrictionEnabled() * @hide */ public static final int RESTRICTION_REASON_DEFAULT = 1; /** * Restriction reason is some kind of timeout that moves the app to a more restricted state. * The threshold should specify how long the app was dormant, in milliseconds. * * For use with noteAppRestrictionEnabled() * @hide */ public static final int RESTRICTION_REASON_DORMANT = 2; /** * Restriction reason to be used when removing a restriction due to direct or indirect usage * of the app, especially to undo any automatic restrictions. * * For use with noteAppRestrictionEnabled() * @hide */ public static final int RESTRICTION_REASON_USAGE = 3; /** * Restriction reason to be used when the user chooses to manually restrict the app, through * UI or command line interface. * * For use with noteAppRestrictionEnabled() * @hide */ public static final int RESTRICTION_REASON_USER = 4; /** * Restriction reason to be used when the user chooses to manually restrict the app on being * prompted by the OS or some anomaly detection algorithm. For example, if the app is causing * high battery drain or affecting system performance and the OS recommends that the user * restrict the app. * * For use with noteAppRestrictionEnabled() * @hide */ public static final int RESTRICTION_REASON_USER_NUDGED = 5; /** * Restriction reason to be used when the OS automatically detects that the app is causing * system health issues such as performance degradation, battery drain, high memory usage, etc. * * For use with noteAppRestrictionEnabled() * @hide */ public static final int RESTRICTION_REASON_SYSTEM_HEALTH = 6; /** * Restriction reason to be used when there is a server-side decision made to restrict an app * that is showing widespread problems on user devices, or violating policy in some way. * * For use with noteAppRestrictionEnabled() * @hide */ public static final int RESTRICTION_REASON_REMOTE_TRIGGER = 7; /** * Restriction reason to be used when some other problem requires restricting the app. * * For use with noteAppRestrictionEnabled() * @hide */ public static final int RESTRICTION_REASON_OTHER = 8; /** @hide */ @IntDef(prefix = { "RESTRICTION_REASON_" }, value = { RESTRICTION_REASON_UNKNOWN, RESTRICTION_REASON_DEFAULT, RESTRICTION_REASON_DORMANT, RESTRICTION_REASON_USAGE, RESTRICTION_REASON_USER, RESTRICTION_REASON_USER_NUDGED, RESTRICTION_REASON_SYSTEM_HEALTH, RESTRICTION_REASON_REMOTE_TRIGGER, RESTRICTION_REASON_OTHER }) @Retention(RetentionPolicy.SOURCE) public @interface RestrictionReason{} /** @hide */ @android.ravenwood.annotation.RavenwoodKeep public static String restrictionLevelToName(@RestrictionLevel int level) { switch (level) { case RESTRICTION_LEVEL_UNKNOWN: return "unknown"; case RESTRICTION_LEVEL_UNRESTRICTED: return "unrestricted"; case RESTRICTION_LEVEL_EXEMPTED: return "exempted"; case RESTRICTION_LEVEL_ADAPTIVE_BUCKET: return "adaptive_bucket"; case RESTRICTION_LEVEL_RESTRICTED_BUCKET: return "restricted_bucket"; case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED: return "background_restricted"; case RESTRICTION_LEVEL_FORCE_STOPPED: return "stopped"; case RESTRICTION_LEVEL_USER_LAUNCH_ONLY: return "user_only"; case RESTRICTION_LEVEL_CUSTOM: return "custom"; case RESTRICTION_LEVEL_MAX: return "max"; default: return String.valueOf(level); } } /** @hide */ public int getFrontActivityScreenCompatMode() { try { return getTaskService().getFrontActivityScreenCompatMode(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @hide */ public void setFrontActivityScreenCompatMode(int mode) { try { getTaskService().setFrontActivityScreenCompatMode(mode); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @hide */ public int getPackageScreenCompatMode(String packageName) { try { return getTaskService().getPackageScreenCompatMode(packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @hide */ public void setPackageScreenCompatMode(String packageName, int mode) { try { getTaskService().setPackageScreenCompatMode(packageName, mode); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @hide */ public boolean getPackageAskScreenCompat(String packageName) { try { return getTaskService().getPackageAskScreenCompat(packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @hide */ public void setPackageAskScreenCompat(String packageName, boolean ask) { try { getTaskService().setPackageAskScreenCompat(packageName, ask); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return the approximate per-application memory class of the current * device. This gives you an idea of how hard a memory limit you should * impose on your application to let the overall system work best. The * returned value is in megabytes; the baseline Android memory class is * 16 (which happens to be the Java heap limit of those devices); some * devices with more memory may return 24 or even higher numbers. */ public int getMemoryClass() { return staticGetMemoryClass(); } /** @hide */ @UnsupportedAppUsage static public int staticGetMemoryClass() { // Really brain dead right now -- just take this from the configured // vm heap size, and assume it is in megabytes and thus ends with "m". String vmHeapSize = SystemProperties.get("dalvik.vm.heapgrowthlimit", ""); if (vmHeapSize != null && !"".equals(vmHeapSize)) { return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1)); } return staticGetLargeMemoryClass(); } /** * Return the approximate per-application memory class of the current * device when an application is running with a large heap. This is the * space available for memory-intensive applications; most applications * should not need this amount of memory, and should instead stay with the * {@link #getMemoryClass()} limit. The returned value is in megabytes. * This may be the same size as {@link #getMemoryClass()} on memory * constrained devices, or it may be significantly larger on devices with * a large amount of available RAM. * *This is the size of the application's Dalvik heap if it has
* specified Note: this method is only intended for debugging and presenting
* task management user interfaces. This should never be used for
* core logic in an application, such as deciding between different
* behaviors based on the information found here. Such uses are
* not supported, and will likely break in the future. For
* example, if multiple applications can be actively running at the
* same time, assumptions made about the meaning of the data here for
* purposes of control flow will be incorrect. Note: this method is only intended for debugging and presenting
* task management user interfaces. This should never be used for
* core logic in an application, such as deciding between different
* behaviors based on the information found here. Such uses are
* not supported, and will likely break in the future. For
* example, if multiple applications can be actively running at the
* same time, assumptions made about the meaning of the data here for
* purposes of control flow will be incorrect. Note: this method is only intended for debugging or implementing
* service management type user interfaces. Typically called by Settings or DocumentsUI, requires
* {@code GET_APP_GRANTED_URI_PERMISSIONS}.
*
* @param packageName application to look for the granted permissions, or {@code null} to get
* granted permissions for all applications
* @return list of granted URI permissions
*
* @hide
* @deprecated use {@link UriGrantsManager#getGrantedUriPermissions(String)} instead.
*/
@Deprecated
public ParceledListSlice Typically called by Settings, requires {@code CLEAR_APP_GRANTED_URI_PERMISSIONS}.
*
* @param packageName application to clear its granted permissions
*
* @hide
* @deprecated use {@link UriGrantsManager#clearGrantedUriPermissions(String)} instead.
*/
@Deprecated
public void clearGrantedUriPermissions(String packageName) {
((UriGrantsManager) mContext.getSystemService(Context.URI_GRANTS_SERVICE))
.clearGrantedUriPermissions(packageName);
}
/**
* Information you can retrieve about any processes that are in an error condition.
*/
public static class ProcessErrorStateInfo implements Parcelable {
/**
* Condition codes
*/
public static final int NO_ERROR = 0;
public static final int CRASHED = 1;
public static final int NOT_RESPONDING = 2;
/**
* The condition that the process is in.
*/
public int condition;
/**
* The process name in which the crash or error occurred.
*/
public String processName;
/**
* The pid of this process; 0 if none
*/
public int pid;
/**
* The kernel user-ID that has been assigned to this process;
* currently this is not a unique ID (multiple applications can have
* the same uid).
*/
public int uid;
/**
* The activity name associated with the error, if known. May be null.
*/
public String tag;
/**
* A short message describing the error condition.
*/
public String shortMsg;
/**
* A long message describing the error condition.
*/
public String longMsg;
/**
* The stack trace where the error originated. May be null.
*/
public String stackTrace;
/**
* to be deprecated: This value will always be null.
*/
public byte[] crashData = null;
public ProcessErrorStateInfo() {
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(condition);
dest.writeString(processName);
dest.writeInt(pid);
dest.writeInt(uid);
dest.writeString(tag);
dest.writeString(shortMsg);
dest.writeString(longMsg);
dest.writeString(stackTrace);
}
public void readFromParcel(Parcel source) {
condition = source.readInt();
processName = source.readString();
pid = source.readInt();
uid = source.readInt();
tag = source.readString();
shortMsg = source.readString();
longMsg = source.readString();
stackTrace = source.readString();
}
public static final @android.annotation.NonNull Creator As of {@link android.os.Build.VERSION_CODES#TIRAMISU Android TIRAMISU}, for regular apps
* this method will only return {@link ProcessErrorStateInfo} records for the processes running
* as the caller's uid, unless the caller has the permission
* {@link android.Manifest.permission#DUMP}.
* The system will return this value instead of {@link #IMPORTANCE_PERCEPTIBLE}
* on Android versions below {@link Build.VERSION_CODES#O}.
*
* On Android version {@link Build.VERSION_CODES#O} and later, this value will still be
* returned for apps with the target API level below {@link Build.VERSION_CODES#O}.
* For apps targeting version {@link Build.VERSION_CODES#O} and later,
* the correct value {@link #IMPORTANCE_PERCEPTIBLE} will be returned.
*/
public static final int IMPORTANCE_PERCEPTIBLE_PRE_26 = 130;
/**
* Constant for {@link #importance}: This process is not something the user
* is directly aware of, but is otherwise perceptible to them to some degree.
*/
public static final int IMPORTANCE_PERCEPTIBLE = 230;
/**
* Constant for {@link #importance}: {@link #IMPORTANCE_CANT_SAVE_STATE} had
* this wrong value
* before {@link Build.VERSION_CODES#O}. Since the {@link Build.VERSION_CODES#O} SDK,
* the value of {@link #IMPORTANCE_CANT_SAVE_STATE} has been fixed.
*
* The system will return this value instead of {@link #IMPORTANCE_CANT_SAVE_STATE}
* on Android versions below {@link Build.VERSION_CODES#O}.
*
* On Android version {@link Build.VERSION_CODES#O} after, this value will still be
* returned for apps with the target API level below {@link Build.VERSION_CODES#O}.
* For apps targeting version {@link Build.VERSION_CODES#O} and later,
* the correct value {@link #IMPORTANCE_CANT_SAVE_STATE} will be returned.
*
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@TestApi
public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170;
/**
* Constant for {@link #importance}: This process contains services
* that should remain running. These are background services apps have
* started, not something the user is aware of, so they may be killed by
* the system relatively freely (though it is generally desired that they
* stay running as long as they want to).
*/
public static final int IMPORTANCE_SERVICE = 300;
/**
* Constant for {@link #importance}: This process is running the foreground
* UI, but the device is asleep so it is not visible to the user. Though the
* system will try hard to keep its process from being killed, in all other
* ways we consider it a kind of cached process, with the limitations that go
* along with that state: network access, running background services, etc.
*/
public static final int IMPORTANCE_TOP_SLEEPING = 325;
/**
* Constant for {@link #importance}: This process is running an
* application that can not save its state, and thus can't be killed
* while in the background. This will be used with apps that have
* {@link android.R.attr#cantSaveState} set on their application tag.
*/
public static final int IMPORTANCE_CANT_SAVE_STATE = 350;
/**
* Constant for {@link #importance}: This process contains cached code
* that is expendable, not actively running any app components we care
* about.
*/
public static final int IMPORTANCE_CACHED = 400;
/**
* @deprecated Renamed to {@link #IMPORTANCE_CACHED}.
*/
public static final int IMPORTANCE_BACKGROUND = IMPORTANCE_CACHED;
/**
* Constant for {@link #importance}: This process is empty of any
* actively running code.
* @deprecated This value is no longer reported, use {@link #IMPORTANCE_CACHED} instead.
*/
@Deprecated
public static final int IMPORTANCE_EMPTY = 500;
/**
* Constant for {@link #importance}: This process does not exist.
*/
public static final int IMPORTANCE_GONE = 1000;
/**
* Convert a proc state to the correspondent IMPORTANCE_* constant. If the return value
* will be passed to a client, use {@link #procStateToImportanceForClient}.
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static @Importance int procStateToImportance(int procState) {
if (procState == PROCESS_STATE_NONEXISTENT) {
return IMPORTANCE_GONE;
} else if (procState >= PROCESS_STATE_HOME) {
return IMPORTANCE_CACHED;
} else if (procState == PROCESS_STATE_HEAVY_WEIGHT) {
return IMPORTANCE_CANT_SAVE_STATE;
} else if (procState >= PROCESS_STATE_TOP_SLEEPING) {
return IMPORTANCE_TOP_SLEEPING;
} else if (procState >= PROCESS_STATE_SERVICE) {
return IMPORTANCE_SERVICE;
} else if (procState >= PROCESS_STATE_TRANSIENT_BACKGROUND) {
return IMPORTANCE_PERCEPTIBLE;
} else if (procState >= PROCESS_STATE_IMPORTANT_FOREGROUND) {
return IMPORTANCE_VISIBLE;
} else if (procState >= PROCESS_STATE_FOREGROUND_SERVICE) {
return IMPORTANCE_FOREGROUND_SERVICE;
} else {
return IMPORTANCE_FOREGROUND;
}
}
/**
* Convert a proc state to the correspondent IMPORTANCE_* constant for a client represented
* by a given {@link Context}, with converting {@link #IMPORTANCE_PERCEPTIBLE}
* and {@link #IMPORTANCE_CANT_SAVE_STATE} to the corresponding "wrong" value if the
* client's target SDK < {@link VERSION_CODES#O}.
* @hide
*/
public static @Importance int procStateToImportanceForClient(int procState,
Context clientContext) {
return procStateToImportanceForTargetSdk(procState,
clientContext.getApplicationInfo().targetSdkVersion);
}
/**
* See {@link #procStateToImportanceForClient}.
* @hide
*/
public static @Importance int procStateToImportanceForTargetSdk(int procState,
int targetSdkVersion) {
final int importance = procStateToImportance(procState);
// For pre O apps, convert to the old, wrong values.
if (targetSdkVersion < VERSION_CODES.O) {
switch (importance) {
case IMPORTANCE_PERCEPTIBLE:
return IMPORTANCE_PERCEPTIBLE_PRE_26;
case IMPORTANCE_TOP_SLEEPING:
return IMPORTANCE_TOP_SLEEPING_PRE_28;
case IMPORTANCE_CANT_SAVE_STATE:
return IMPORTANCE_CANT_SAVE_STATE_PRE_26;
}
}
return importance;
}
/** @hide */
public static int importanceToProcState(@Importance int importance) {
if (importance == IMPORTANCE_GONE) {
return PROCESS_STATE_NONEXISTENT;
} else if (importance >= IMPORTANCE_CACHED) {
return PROCESS_STATE_HOME;
} else if (importance >= IMPORTANCE_CANT_SAVE_STATE) {
return PROCESS_STATE_HEAVY_WEIGHT;
} else if (importance >= IMPORTANCE_TOP_SLEEPING) {
return PROCESS_STATE_TOP_SLEEPING;
} else if (importance >= IMPORTANCE_SERVICE) {
return PROCESS_STATE_SERVICE;
} else if (importance >= IMPORTANCE_PERCEPTIBLE) {
return PROCESS_STATE_TRANSIENT_BACKGROUND;
} else if (importance >= IMPORTANCE_VISIBLE) {
return PROCESS_STATE_IMPORTANT_FOREGROUND;
} else if (importance >= IMPORTANCE_TOP_SLEEPING_PRE_28) {
return PROCESS_STATE_IMPORTANT_FOREGROUND;
} else if (importance >= IMPORTANCE_FOREGROUND_SERVICE) {
return PROCESS_STATE_FOREGROUND_SERVICE;
// TODO: Asymmetrical mapping for LOCATION service type. Ok?
} else {
return PROCESS_STATE_TOP;
}
}
/**
* The relative importance level that the system places on this process.
* These constants are numbered so that "more important" values are
* always smaller than "less important" values.
*/
public @Importance int importance;
/**
* An additional ordering within a particular {@link #importance}
* category, providing finer-grained information about the relative
* utility of processes within a category. This number means nothing
* except that a smaller values are more recently used (and thus
* more important). Currently an LRU value is only maintained for
* the {@link #IMPORTANCE_CACHED} category, though others may
* be maintained in the future.
*/
public int lru;
/**
* Constant for {@link #importanceReasonCode}: nothing special has
* been specified for the reason for this level.
*/
public static final int REASON_UNKNOWN = 0;
/**
* Constant for {@link #importanceReasonCode}: one of the application's
* content providers is being used by another process. The pid of
* the client process is in {@link #importanceReasonPid} and the
* target provider in this process is in
* {@link #importanceReasonComponent}.
*/
public static final int REASON_PROVIDER_IN_USE = 1;
/**
* Constant for {@link #importanceReasonCode}: one of the application's
* content providers is being used by another process. The pid of
* the client process is in {@link #importanceReasonPid} and the
* target provider in this process is in
* {@link #importanceReasonComponent}.
*/
public static final int REASON_SERVICE_IN_USE = 2;
/**
* The reason for {@link #importance}, if any.
*/
public int importanceReasonCode;
/**
* For the specified values of {@link #importanceReasonCode}, this
* is the process ID of the other process that is a client of this
* process. This will be 0 if no other process is using this one.
*/
public int importanceReasonPid;
/**
* For the specified values of {@link #importanceReasonCode}, this
* is the name of the component that is being used in this process.
*/
public ComponentName importanceReasonComponent;
/**
* When {@link #importanceReasonPid} is non-0, this is the importance
* of the other pid. @hide
*/
public int importanceReasonImportance;
/**
* Current process state, as per PROCESS_STATE_* constants.
* @hide
*/
@UnsupportedAppUsage
public int processState;
/**
* Whether the app is focused in multi-window environment.
* @hide
*/
public boolean isFocused;
/**
* Copy of {@link com.android.server.am.ProcessRecord#lastActivityTime} of the process.
* @hide
*/
public long lastActivityTime;
public RunningAppProcessInfo() {
importance = IMPORTANCE_FOREGROUND;
importanceReasonCode = REASON_UNKNOWN;
processState = PROCESS_STATE_IMPORTANT_FOREGROUND;
isFocused = false;
lastActivityTime = 0;
}
public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) {
processName = pProcessName;
pid = pPid;
pkgList = pArr;
isFocused = false;
lastActivityTime = 0;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(processName);
dest.writeInt(pid);
dest.writeInt(uid);
dest.writeStringArray(pkgList);
dest.writeStringArray(pkgDeps);
dest.writeInt(this.flags);
dest.writeInt(lastTrimLevel);
dest.writeInt(importance);
dest.writeInt(lru);
dest.writeInt(importanceReasonCode);
dest.writeInt(importanceReasonPid);
ComponentName.writeToParcel(importanceReasonComponent, dest);
dest.writeInt(importanceReasonImportance);
dest.writeInt(processState);
dest.writeInt(isFocused ? 1 : 0);
dest.writeLong(lastActivityTime);
}
public void readFromParcel(Parcel source) {
processName = source.readString();
pid = source.readInt();
uid = source.readInt();
pkgList = source.readStringArray();
pkgDeps = source.readStringArray();
flags = source.readInt();
lastTrimLevel = source.readInt();
importance = source.readInt();
lru = source.readInt();
importanceReasonCode = source.readInt();
importanceReasonPid = source.readInt();
importanceReasonComponent = ComponentName.readFromParcel(source);
importanceReasonImportance = source.readInt();
processState = source.readInt();
isFocused = source.readInt() != 0;
lastActivityTime = source.readLong();
}
public static final @android.annotation.NonNull Creator Note: this method is only intended for debugging or building
* a user-facing process management UI. The user may chose to do this, if they see that an app is consuming an unreasonable
* amount of battery while in the background. If true, any work that the app tries to do will be aggressively restricted while it is in
* the background. At a minimum, jobs and alarms will not execute and foreground services
* cannot be started unless an app activity is in the foreground. Note that these restrictions stay in effect even when the device is charging. Note: this method is only intended for testing framework. Note: this method is only intended for debugging or building
* a user-facing process management UI. Note: System stores this historical information in a ring buffer and only
* the most recent records will be returned. Note: System stores this historical information in a ring buffer and only
* the most recent records will be returned. Note: callback will be removed automatically after being triggered. Note: callback will not wait for {@link Activity#reportFullyDrawn} to occur.
* Timestamp for fully drawn may be added after callback occurs. Set callback after invoking
* {@link Activity#reportFullyDrawn} if timestamp for fully drawn is required. Note: if start records have already been retrieved, the callback will be
* invoked immediately on the specified executor with the previously resolved AppStartInfo. Note: callback is asynchronous and should be made from a background thread.
* Note: timestamps added after {@link Activity#reportFullyDrawn} is called
* will be discarded. Note: will overwrite existing timestamp if called with same key. Note: System stores this historical information in a ring buffer and only
* the most recent records will be returned. Note: In the case that this application was bound to an external service
* with flag {@link android.content.Context#BIND_EXTERNAL_SERVICE}, the process of that external
* service will be included in this package's exit info. This would be useful for the calling app to save its stateful data: if it's
* killed later for any reason, the new process of the app can know what the
* previous process of the app was doing. For instance, you could use this to encode
* the current level in a game, or a set of features/experiments that were enabled. Later you
* could analyze under what circumstances the app tends to crash or use too much memory.
* However, it's not suggested to rely on this to restore the applications previous UI state
* or so, it's only meant for analyzing application healthy status. System might decide to throttle the calls to this API; so call this API in a reasonable
* manner, excessive calls to this API could result a {@link java.lang.RuntimeException}.
* This will return {@link RunningAppProcessInfo#IMPORTANCE_GONE} on all other UIDs,
* regardless of if they're valid or not.
*
* Privileged system apps may prefer this API to {@link #getUidImportance(int)} to
* avoid requesting the permission {@link Manifest.permission#PACKAGE_USAGE_STATS}, which
* would allow access to APIs that return more senstive information.
*
* @hide
*/
@FlaggedApi(Flags.FLAG_GET_BINDING_UID_IMPORTANCE)
@SystemApi
@RequiresPermission(Manifest.permission.GET_BINDING_UID_IMPORTANCE)
public @RunningAppProcessInfo.Importance int getBindingUidImportance(int uid) {
try {
int procState = getService().getBindingUidProcessState(uid,
mContext.getOpPackageName());
return RunningAppProcessInfo.procStateToImportanceForClient(procState, mContext);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Callback to get reports about changes to the importance of a uid. Use with
* {@link #addOnUidImportanceListener}.
* @hide
*/
@SystemApi
public interface OnUidImportanceListener {
/**
* The importance if a given uid has changed. Will be one of the importance
* values in {@link RunningAppProcessInfo};
* {@link RunningAppProcessInfo#IMPORTANCE_GONE IMPORTANCE_GONE} will be reported
* when the uid is no longer running at all. This callback will happen on a thread
* from a thread pool, not the main UI thread.
* @param uid The uid whose importance has changed.
* @param importance The new importance value as per {@link RunningAppProcessInfo}.
*/
void onUidImportance(int uid, @RunningAppProcessInfo.Importance int importance);
}
/**
* Start monitoring changes to the importance of all uids running in the system.
* @param listener The listener callback that will receive change reports.
* @param importanceCutpoint The level of importance in which the caller is interested
* in differences. For example, if {@link RunningAppProcessInfo#IMPORTANCE_PERCEPTIBLE}
* is used here, you will receive a call each time a uids importance transitions between
* being <= {@link RunningAppProcessInfo#IMPORTANCE_PERCEPTIBLE} and
* > {@link RunningAppProcessInfo#IMPORTANCE_PERCEPTIBLE}.
*
* The caller must hold the {@link android.Manifest.permission#PACKAGE_USAGE_STATS}
* permission to use this feature. Calling this API with the same instance of {@code listener} without
* unregistering with {@link #removeOnUidImportanceListener} before it will result in
* an {@link IllegalArgumentException}. Calling this API with the same instance of {@code listener} without
* unregistering with {@link #removeOnUidImportanceListener} before it will result in
* an {@link IllegalArgumentException}. Note: this method is only intended for debugging or building
* a user-facing process management UI. As of {@link android.os.Build.VERSION_CODES#Q Android Q}, for regular apps this method
* will only return information about the memory info for the processes running as the
* caller's uid; no other process memory info is available and will be zero.
* Also of {@link android.os.Build.VERSION_CODES#Q Android Q} the sample rate allowed
* by this API is significantly limited, if called faster the limit you will receive the
* same data as the previous call. On devices that run Android 14 or higher,
* third party applications can only use this API to kill their own processes.
* You must hold the permission
* {@link android.Manifest.permission#FORCE_STOP_PACKAGES} to be able to
* call this method.
*
* @param packageName The name of the package to be stopped.
* @param userId The user for which the running package is to be stopped.
*
* @hide This is not available to third party applications due to
* it allowing them to break other applications by stopping their
* services, removing their alarms, etc.
*/
@UnsupportedAppUsage
public void forceStopPackageAsUser(String packageName, int userId) {
try {
getService().forceStopPackage(packageName, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @see #forceStopPackageAsUser(String, int)
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)
public void forceStopPackage(String packageName) {
forceStopPackageAsUser(packageName, mContext.getUserId());
}
/**
* Similar to {@link #forceStopPackageAsUser(String, int)} but will also stop the package even
* when the user is in the stopping state.
*
* @hide
*/
@RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)
public void forceStopPackageAsUserEvenWhenStopping(String packageName, @UserIdInt int userId) {
try {
getService().forceStopPackageEvenWhenStopping(packageName, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Sets the current locales of the device. Calling app must have the permission
* {@code android.permission.CHANGE_CONFIGURATION} and
* {@code android.permission.WRITE_SETTINGS}.
*
* @hide
*/
@SystemApi
public void setDeviceLocales(@NonNull LocaleList locales) {
LocalePicker.updateLocales(locales);
}
/**
* Returns a list of supported locales by this system. It includes all locales that are
* selectable by the user, potentially including locales that the framework does not have
* translated resources for. To get locales that the framework has translated resources for, use
* {@code Resources.getSystem().getAssets().getLocales()} instead.
*
* @hide
*/
@SystemApi
public @NonNull Collection Test Harness Mode is a feature that allows devices to run without human interaction in a
* device farm/testing harness (such as Firebase Test Lab). You should check this method if you
* want your app to behave differently when running in a test harness to skip setup screens that
* would impede UI testing. e.g. a keyboard application that has a full screen setup page for
* the first time it is launched.
*
* Note that you should not use this to determine whether or not your app is running
* an instrumentation test, as it is not set for a standard device running a test.
*/
public static boolean isRunningInUserTestHarness() {
return SystemProperties.getBoolean("persist.sys.test_harness", false);
}
/**
* Unsupported compiled sdk warning should always be shown for the intput activity
* even in cases where the system would normally not show the warning. E.g. when running in a
* test harness.
*
* @param activity The component name of the activity to always show the warning for.
*
* @hide
*/
@TestApi
public void alwaysShowUnsupportedCompileSdkWarning(ComponentName activity) {
try {
getTaskService().alwaysShowUnsupportedCompileSdkWarning(activity);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Returns the launch count of each installed package.
*
* @hide
*/
/*public Map This method will allow the user to launch activities on that display, and it's typically
* used only on automotive builds when the vehicle has multiple displays (you can verify if it's
* supported by calling {@link UserManager#isVisibleBackgroundUsersSupported()}).
*
* NOTE: differently from {@link #switchUser(int)}, which stops the current foreground
* user before starting a new one, this method does not stop the previous user running in
* background in the display, and it will return {@code false} in this case. It's up to the
* caller to call {@link #stopUser(int)} before starting a new user.
*
* @param userId user to be started in the display. It will return {@code false} if the user is
* a profile, the {@link #getCurrentUser()}, the {@link UserHandle#SYSTEM system user}, or
* does not exist.
*
* @param displayId id of the display.
*
* @return whether the operation succeeded. Notice that if the user was already started in such
* display before, it will return {@code false}.
*
* @throws UnsupportedOperationException if the device does not support background users on
* secondary displays.
*
* @hide
*/
@TestApi
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS})
public boolean startUserInBackgroundVisibleOnDisplay(@UserIdInt int userId, int displayId) {
if (!UserManager.isVisibleBackgroundUsersEnabled()) {
throw new UnsupportedOperationException(
"device does not support users on secondary displays");
}
try {
return getService().startUserInBackgroundVisibleOnDisplay(userId, displayId,
/* unlockProgressListener= */ null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Gets the id of displays that can be used by
* {@link #startUserInBackgroundOnSecondaryDisplay(int, int)}.
*
* @hide
*/
@TestApi
@Nullable
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS})
public int[] getDisplayIdsForStartingVisibleBackgroundUsers() {
try {
return getService().getDisplayIdsForStartingVisibleBackgroundUsers();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Gets the message that is shown when a user is switched from.
*
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_USERS)
public @Nullable String getSwitchingFromUserMessage() {
try {
return getService().getSwitchingFromUserMessage();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Gets the message that is shown when a user is switched to.
*
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_USERS)
public @Nullable String getSwitchingToUserMessage() {
try {
return getService().getSwitchingToUserMessage();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Uses the value defined by the platform.
*
* @hide
*/
@TestApi
public static final int STOP_USER_ON_SWITCH_DEFAULT = -1;
/**
* Overrides value defined by the platform and stop user on switch.
*
* @hide
*/
@TestApi
public static final int STOP_USER_ON_SWITCH_TRUE = 1;
/**
* Overrides value defined by the platform and don't stop user on switch.
*
* @hide
*/
@TestApi
public static final int STOP_USER_ON_SWITCH_FALSE = 0;
/** @hide */
@IntDef(prefix = { "STOP_USER_ON_SWITCH_" }, value = {
STOP_USER_ON_SWITCH_DEFAULT,
STOP_USER_ON_SWITCH_TRUE,
STOP_USER_ON_SWITCH_FALSE
})
@Retention(RetentionPolicy.SOURCE)
public @interface StopUserOnSwitch {}
/**
* Sets whether the current foreground user (and its profiles) should be stopped after switched
* out.
*
* Should only be used on tests. Doesn't apply to {@link UserHandle#SYSTEM system user}.
*
* @hide
*/
@TestApi
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS})
public void setStopUserOnSwitch(@StopUserOnSwitch int value) {
try {
getService().setStopUserOnSwitch(value);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Starts a profile.
* To be used with non-managed profiles, managed profiles should use
* {@link UserManager#requestQuietModeEnabled}
*
* @param userHandle user handle of the profile.
* @return true if the profile has been successfully started or if the profile is already
* running, false if profile failed to start.
* @throws IllegalArgumentException if {@code userHandle} is not a profile.
*
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
public boolean startProfile(@NonNull UserHandle userHandle) {
try {
return getService().startProfile(userHandle.getIdentifier());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Stops a running profile.
* To be used with non-managed profiles, managed profiles should use
* {@link UserManager#requestQuietModeEnabled}
*
* @param userHandle user handle of the profile.
* @return true if the profile has been successfully stopped or is already stopped. Otherwise
* the exceptions listed below are thrown.
* @throws IllegalArgumentException if {@code userHandle} is not a profile.
*
* @hide
*/
@SystemApi
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
public boolean stopProfile(@NonNull UserHandle userHandle) {
try {
return getService().stopProfile(userHandle.getIdentifier());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Updates the MCC (Mobile Country Code) and MNC (Mobile Network Code) in the
* system configuration.
*
* @param mcc The new MCC.
* @param mnc The new MNC.
* @throws RemoteException; IllegalArgumentException if mcc or mnc is null;
* @return Returns {@code true} if the configuration was updated successfully;
* {@code false} otherwise.
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@TestApi
@RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION)
public boolean updateMccMncConfiguration(@NonNull String mcc, @NonNull String mnc) {
if (mcc == null || mnc == null) {
throw new IllegalArgumentException("mcc or mnc cannot be null.");
}
try {
return getService().updateMccMncConfiguration(mcc, mnc);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Stops the given {@code userId}.
*
* NOTE: on systems that support
* {@link UserManager#isVisibleBackgroundUsersSupported() background users on secondary
* displays}, this method will also unassign the user from the display it was started on.
*
* @hide
*/
@SuppressLint("UnflaggedApi") // @TestApi without associated feature.
@TestApi
@RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public boolean stopUser(@UserIdInt int userId) {
if (userId == UserHandle.USER_SYSTEM) {
return false;
}
try {
return USER_OP_SUCCESS == getService().stopUserWithCallback(
userId, /* callback= */ null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** {@hide} */
public static final int FLAG_OR_STOPPED = 1 << 0;
/** {@hide} */
public static final int FLAG_AND_LOCKED = 1 << 1;
/** {@hide} */
public static final int FLAG_AND_UNLOCKED = 1 << 2;
/** {@hide} */
public static final int FLAG_AND_UNLOCKING_OR_UNLOCKED = 1 << 3;
/**
* Return whether the given user is actively running. This means that
* the user is in the "started" state, not "stopped" -- it is currently
* allowed to run code through scheduled alarms, receiving broadcasts,
* etc. A started user may be either the current foreground user or a
* background user; the result here does not distinguish between the two.
* @param userId the user's id. Zero indicates the default user.
* @hide
*/
@UnsupportedAppUsage
public boolean isUserRunning(int userId) {
try {
return getService().isUserRunning(userId, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** {@hide} */
public boolean isVrModePackageEnabled(ComponentName component) {
try {
return getService().isVrModePackageEnabled(component);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Perform a system dump of various state associated with the given application
* package name. This call blocks while the dump is being performed, so should
* not be done on a UI thread. The data will be written to the given file
* descriptor as text.
* @param fd The file descriptor that the dump should be written to. The file
* descriptor is not closed by this function; the caller continues to
* own it.
* @param packageName The name of the package that is to be dumped.
*/
@RequiresPermission(Manifest.permission.DUMP)
public void dumpPackageState(FileDescriptor fd, String packageName) {
dumpPackageStateStatic(fd, packageName);
}
/**
* @hide
*/
public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout);
dumpService(pw, fd, "package", new String[] { packageName });
pw.println();
dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] {
"-a", "package", packageName });
pw.println();
dumpService(pw, fd, "meminfo", new String[] { "--local", "--package", packageName });
pw.println();
dumpService(pw, fd, ProcessStats.SERVICE_NAME, new String[] { packageName });
pw.println();
dumpService(pw, fd, "usagestats", new String[] { packageName });
pw.println();
dumpService(pw, fd, BatteryStats.SERVICE_NAME, new String[] { packageName });
pw.flush();
}
/**
* @hide
*/
@android.ravenwood.annotation.RavenwoodReplace
public static boolean isSystemReady() {
if (!sSystemReady) {
if (ActivityThread.isSystem()) {
sSystemReady =
LocalServices.getService(ActivityManagerInternal.class).isSystemReady();
} else {
// Since this is being called from outside system server, system should be
// ready by now.
sSystemReady = true;
}
}
return sSystemReady;
}
/** @hide */
public static boolean isSystemReady$ravenwood() {
// Ravenwood environment is always considered as booted and ready
return true;
}
/**
* @hide
*/
public static void broadcastStickyIntent(Intent intent, int userId) {
broadcastStickyIntent(intent, AppOpsManager.OP_NONE, null, userId);
}
/**
* Convenience for sending a sticky broadcast. For internal use only.
*
* @hide
*/
public static void broadcastStickyIntent(Intent intent, int appOp, int userId) {
broadcastStickyIntent(intent, appOp, null, userId);
}
/**
* Convenience for sending a sticky broadcast. For internal use only.
*
* @hide
*/
public static void broadcastStickyIntent(Intent intent, int appOp, Bundle options, int userId) {
broadcastStickyIntent(intent, null, appOp, options, userId);
}
/**
* Convenience for sending a sticky broadcast. For internal use only.
*
* @hide
*/
public static void broadcastStickyIntent(Intent intent, String[] excludedPackages,
int appOp, Bundle options, int userId) {
try {
getService().broadcastIntentWithFeature(
null, null, intent, null, null, Activity.RESULT_OK, null, null,
null /*requiredPermissions*/, null /*excludedPermissions*/,
excludedPackages, appOp, options, false, true, userId);
} catch (RemoteException ex) {
}
}
/**
* @hide
*/
@TestApi
public static void resumeAppSwitches() throws RemoteException {
getService().resumeAppSwitches();
}
/**
* @hide
*/
public static void noteWakeupAlarm(PendingIntent ps, WorkSource workSource, int sourceUid,
String sourcePkg, String tag) {
try {
getService().noteWakeupAlarm((ps != null) ? ps.getTarget() : null, workSource,
sourceUid, sourcePkg, tag);
} catch (RemoteException ex) {
}
}
/**
* @hide
*/
public static void noteAlarmStart(PendingIntent ps, WorkSource workSource, int sourceUid,
String tag) {
try {
getService().noteAlarmStart((ps != null) ? ps.getTarget() : null, workSource,
sourceUid, tag);
} catch (RemoteException ex) {
}
}
/**
* @hide
*/
public static void noteAlarmFinish(PendingIntent ps, WorkSource workSource, int sourceUid,
String tag) {
try {
getService().noteAlarmFinish((ps != null) ? ps.getTarget() : null, workSource,
sourceUid, tag);
} catch (RemoteException ex) {
}
}
/**
* @hide
*/
@UnsupportedAppUsage
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static IActivityTaskManager getTaskService() {
return ActivityTaskManager.getService();
}
@UnsupportedAppUsage
private static final Singleton This API only works if the calling process has been marked as
* {@link ApplicationInfo#FLAG_DEBUGGABLE} or this is running on a debuggable
* (userdebug or eng) build. Callers can optionally implement {@link #ACTION_REPORT_HEAP_LIMIT} to directly
* handle heap limit reports themselves. You must hold the permission
* {@link android.Manifest.permission#FORCE_STOP_PACKAGES} to be able to
* call this method.
* In other words, you generally want to use an Intent here that does not specify
* {@link Intent#FLAG_ACTIVITY_NEW_TASK} or {@link Intent#FLAG_ACTIVITY_NEW_DOCUMENT},
* and let the system do the right thing. When {@code delayedDurationMs} is {@code 0}, it will clears any previously
* set forced delays.
*
* Note: This method is only intended for testing and it only
* works for packages that are already running.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.DUMP)
public void forceDelayBroadcastDelivery(@NonNull String targetPackage,
@IntRange(from = 0) long delayedDurationMs) {
try {
getService().forceDelayBroadcastDelivery(targetPackage, delayedDurationMs);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Checks if the process represented by the given {@code pid} is frozen.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.DUMP)
public boolean isProcessFrozen(int pid) {
try {
return getService().isProcessFrozen(pid);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Internal method for logging API starts. Used with
* FGS metrics logging. Is called by APIs that are
* used with FGS to log an API event (eg when
* the camera starts).
* @hide
*
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE)
public void noteForegroundResourceUseBegin(@ForegroundServiceApiType int apiType,
int uid, int pid) throws SecurityException {
try {
getService().logFgsApiBegin(apiType, uid, pid);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Internal method for logging API end. Used with
* FGS metrics logging. Is called by APIs that are
* used with FGS to log an API event (eg when
* the camera starts).
* @hide
*
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE)
public void noteForegroundResourceUseEnd(@ForegroundServiceApiType int apiType,
int uid, int pid) throws SecurityException {
try {
getService().logFgsApiEnd(apiType, uid, pid);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* @return The reason code of whether or not the given UID should be exempted from background
* restrictions here.
*
*
* Note: Call it with caution as it'll try to acquire locks in other services.
*
* The {@code enabled} value determines whether the state is being applied or removed.
* Not all restrictions are actual restrictions. For example,
* {@link #RESTRICTION_LEVEL_ADAPTIVE} is a normal state, where there is default lifecycle
* management applied to the app. Also, {@link #RESTRICTION_LEVEL_EXEMPTED} is used when the
* app is being put in a power-save allowlist.
*
* Example arguments when user force-stops an app from Settings:
* android:largeHeap="true"
in its manifest.
*/
public int getLargeMemoryClass() {
return staticGetLargeMemoryClass();
}
/** @hide */
static public int staticGetLargeMemoryClass() {
// Really brain dead right now -- just take this from the configured
// vm heap size, and assume it is in megabytes and thus ends with "m".
String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m");
return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length() - 1));
}
/**
* Returns true if this is a low-RAM device. Exactly whether a device is low-RAM
* is ultimately up to the device configuration, but currently it generally means
* something with 1GB or less of RAM. This is mostly intended to be used by apps
* to determine whether they should turn off certain features that require more RAM.
*/
public boolean isLowRamDevice() {
return isLowRamDeviceStatic();
}
/** @hide */
@UnsupportedAppUsage
public static boolean isLowRamDeviceStatic() {
return RoSystemProperties.CONFIG_LOW_RAM ||
(Build.IS_DEBUGGABLE && DEVELOPMENT_FORCE_LOW_RAM);
}
/**
* Returns true if this is a small battery device. Exactly whether a device is considered to be
* small battery is ultimately up to the device configuration, but currently it generally means
* something in the class of a device with 1000 mAh or less. This is mostly intended to be used
* to determine whether certain features should be altered to account for a drastically smaller
* battery.
* @hide
*/
public static boolean isSmallBatteryDevice() {
return RoSystemProperties.CONFIG_SMALL_BATTERY;
}
/**
* Used by persistent processes to determine if they are running on a
* higher-end device so should be okay using hardware drawing acceleration
* (which tends to consume a lot more RAM).
* @hide
*/
@TestApi
static public boolean isHighEndGfx() {
return !isLowRamDeviceStatic()
&& !RoSystemProperties.CONFIG_AVOID_GFX_ACCEL
&& !Resources.getSystem()
.getBoolean(com.android.internal.R.bool.config_avoidGfxAccel);
}
/**
* Return the total number of bytes of RAM this device has.
* @hide
*/
@TestApi
public long getTotalRam() {
MemInfoReader memreader = new MemInfoReader();
memreader.readMemInfo();
return memreader.getTotalSize();
}
/**
* TODO(b/80414790): Remove once no longer on hiddenapi-light-greylist.txt
* @hide
* @deprecated Use {@link ActivityTaskManager#getMaxRecentTasksStatic()}
*/
@Deprecated
@UnsupportedAppUsage
static public int getMaxRecentTasksStatic() {
return ActivityTaskManager.getMaxRecentTasksStatic();
}
/**
* Information you can set and retrieve about the current activity within the recent task list.
*/
public static class TaskDescription implements Parcelable {
/** @hide */
public static final String ATTR_TASKDESCRIPTION_PREFIX = "task_description_";
private static final String ATTR_TASKDESCRIPTIONLABEL =
ATTR_TASKDESCRIPTION_PREFIX + "label";
private static final String ATTR_TASKDESCRIPTIONCOLOR_PRIMARY =
ATTR_TASKDESCRIPTION_PREFIX + "color";
private static final String ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND =
ATTR_TASKDESCRIPTION_PREFIX + "color_background";
private static final String ATTR_TASKDESCRIPTIONICON_FILENAME =
ATTR_TASKDESCRIPTION_PREFIX + "icon_filename";
private static final String ATTR_TASKDESCRIPTIONICON_RESOURCE =
ATTR_TASKDESCRIPTION_PREFIX + "icon_resource";
private static final String ATTR_TASKDESCRIPTIONICON_RESOURCE_PACKAGE =
ATTR_TASKDESCRIPTION_PREFIX + "icon_package";
private static final String ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND_FLOATING =
ATTR_TASKDESCRIPTION_PREFIX + "color_background_floating";
private String mLabel;
@Nullable
private Icon mIcon;
private String mIconFilename;
private int mColorPrimary;
private int mColorBackground;
private int mColorBackgroundFloating;
private int mStatusBarColor;
private int mNavigationBarColor;
@Appearance
private int mSystemBarsAppearance;
private boolean mEnsureStatusBarContrastWhenTransparent;
private boolean mEnsureNavigationBarContrastWhenTransparent;
private int mResizeMode;
private int mMinWidth;
private int mMinHeight;
/**
* Provides a convenient way to set the fields of a {@link TaskDescription} when creating a
* new instance.
*/
public static final class Builder {
/**
* Default values for the TaskDescription
*/
@Nullable
private String mLabel = null;
@DrawableRes
private int mIconRes = Resources.ID_NULL;
private int mPrimaryColor = 0;
private int mBackgroundColor = 0;
private int mStatusBarColor = 0;
private int mNavigationBarColor = 0;
/**
* Set the label to use in the TaskDescription.
* @param label A label and description of the current state of this activity.
* @return The same instance of the builder.
*/
@NonNull
public Builder setLabel(@Nullable String label) {
this.mLabel = label;
return this;
}
/**
* Set the drawable resource of the icon to use in the TaskDescription.
* @param iconRes A drawable resource of an icon that represents the current state of
* this activity.
* @return The same instance of the builder.
*/
@NonNull
public Builder setIcon(@DrawableRes int iconRes) {
this.mIconRes = iconRes;
return this;
}
/**
* Set the primary color to use in the TaskDescription.
* @param color A color to override the theme's primary color. The color must be opaque.
* @return The same instance of the builder.
*/
@NonNull
public Builder setPrimaryColor(@ColorInt int color) {
this.mPrimaryColor = color;
return this;
}
/**
* Set the background color to use in the TaskDescription.
* @param color A color to override the theme's background color. The color must be
* opaque.
* @return The same instance of the builder.
*/
@NonNull
public Builder setBackgroundColor(@ColorInt int color) {
this.mBackgroundColor = color;
return this;
}
/**
* Set the status bar color to use in the TaskDescription.
* @param color A color to override the theme's status bar color.
* @return The same instance of the builder.
*/
@NonNull
public Builder setStatusBarColor(@ColorInt int color) {
this.mStatusBarColor = color;
return this;
}
/**
* Set the navigation bar color to use in the TaskDescription.
* @param color A color to override the theme's navigation bar color.
* @return The same instance of the builder.
*/
@NonNull
public Builder setNavigationBarColor(@ColorInt int color) {
this.mNavigationBarColor = color;
return this;
}
/**
* Build the TaskDescription.
* @return the TaskDescription object.
*/
@NonNull
public TaskDescription build() {
final Icon icon = mIconRes == Resources.ID_NULL ? null :
Icon.createWithResource(ActivityThread.currentPackageName(), mIconRes);
return new TaskDescription(mLabel, icon, mPrimaryColor, mBackgroundColor,
mStatusBarColor, mNavigationBarColor, 0, false, false,
RESIZE_MODE_RESIZEABLE, -1, -1, 0);
}
}
/**
* Creates the TaskDescription to the specified values.
*
* @param label A label and description of the current state of this task.
* @param iconRes A drawable resource of an icon that represents the current state of this
* activity.
* @param colorPrimary A color to override the theme's primary color. This color must be
* opaque.
*
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public TaskDescription(String label, @DrawableRes int iconRes, int colorPrimary) {
this(label, Icon.createWithResource(ActivityThread.currentPackageName(), iconRes),
colorPrimary, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
throw new RuntimeException("A TaskDescription's primary color should be opaque");
}
}
/**
* Creates the TaskDescription to the specified values.
*
* @param label A label and description of the current state of this activity.
* @param iconRes A drawable resource of an icon that represents the current state of this
* activity.
*
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public TaskDescription(String label, @DrawableRes int iconRes) {
this(label, Icon.createWithResource(ActivityThread.currentPackageName(), iconRes),
0, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
}
/**
* Creates the TaskDescription to the specified values.
*
* @param label A label and description of the current state of this activity.
*
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public TaskDescription(String label) {
this(label, null, 0, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
}
/**
* Creates an empty TaskDescription.
*
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public TaskDescription() {
this(null, null, 0, 0, 0, 0, 0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
}
/**
* Creates the TaskDescription to the specified values.
*
* @param label A label and description of the current state of this task.
* @param icon An icon that represents the current state of this task.
* @param colorPrimary A color to override the theme's primary color. This color must be
* opaque.
*
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public TaskDescription(String label, Bitmap icon, int colorPrimary) {
this(label, icon != null ? Icon.createWithBitmap(icon) : null, colorPrimary, 0, 0, 0,
0, false, false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
throw new RuntimeException("A TaskDescription's primary color should be opaque");
}
}
/**
* Creates the TaskDescription to the specified values.
*
* @param label A label and description of the current state of this activity.
* @param icon An icon that represents the current state of this activity.
*
* @deprecated Use {@link Builder} instead.
*/
@Deprecated
public TaskDescription(String label, Bitmap icon) {
this(label, icon != null ? Icon.createWithBitmap(icon) : null, 0, 0, 0, 0, 0, false,
false, RESIZE_MODE_RESIZEABLE, -1, -1, 0);
}
/** @hide */
public TaskDescription(@Nullable String label, @Nullable Icon icon,
int colorPrimary, int colorBackground,
int statusBarColor, int navigationBarColor,
@Appearance int systemBarsAppearance,
boolean ensureStatusBarContrastWhenTransparent,
boolean ensureNavigationBarContrastWhenTransparent, int resizeMode, int minWidth,
int minHeight, int colorBackgroundFloating) {
mLabel = label;
mIcon = icon;
mColorPrimary = colorPrimary;
mColorBackground = colorBackground;
mStatusBarColor = statusBarColor;
mNavigationBarColor = navigationBarColor;
mSystemBarsAppearance = systemBarsAppearance;
mEnsureStatusBarContrastWhenTransparent = ensureStatusBarContrastWhenTransparent;
mEnsureNavigationBarContrastWhenTransparent =
ensureNavigationBarContrastWhenTransparent;
mResizeMode = resizeMode;
mMinWidth = minWidth;
mMinHeight = minHeight;
mColorBackgroundFloating = colorBackgroundFloating;
}
/**
* Creates a copy of another TaskDescription.
*/
public TaskDescription(TaskDescription td) {
copyFrom(td);
}
/**
* Copies this the values from another TaskDescription.
* @hide
*/
public void copyFrom(TaskDescription other) {
mLabel = other.mLabel;
mIcon = other.mIcon;
mIconFilename = other.mIconFilename;
mColorPrimary = other.mColorPrimary;
mColorBackground = other.mColorBackground;
mStatusBarColor = other.mStatusBarColor;
mNavigationBarColor = other.mNavigationBarColor;
mSystemBarsAppearance = other.mSystemBarsAppearance;
mEnsureStatusBarContrastWhenTransparent = other.mEnsureStatusBarContrastWhenTransparent;
mEnsureNavigationBarContrastWhenTransparent =
other.mEnsureNavigationBarContrastWhenTransparent;
mResizeMode = other.mResizeMode;
mMinWidth = other.mMinWidth;
mMinHeight = other.mMinHeight;
mColorBackgroundFloating = other.mColorBackgroundFloating;
}
/**
* Copies values from another TaskDescription, but preserves the hidden fields if they
* weren't set on {@code other}. Public fields will be overwritten anyway.
* @hide
*/
public void copyFromPreserveHiddenFields(TaskDescription other) {
mLabel = other.mLabel;
mIcon = other.mIcon;
mIconFilename = other.mIconFilename;
mColorPrimary = other.mColorPrimary;
if (other.mColorBackground != 0) {
mColorBackground = other.mColorBackground;
}
if (other.mStatusBarColor != 0) {
mStatusBarColor = other.mStatusBarColor;
}
if (other.mNavigationBarColor != 0) {
mNavigationBarColor = other.mNavigationBarColor;
}
if (other.mSystemBarsAppearance != 0) {
mSystemBarsAppearance = other.mSystemBarsAppearance;
}
mEnsureStatusBarContrastWhenTransparent = other.mEnsureStatusBarContrastWhenTransparent;
mEnsureNavigationBarContrastWhenTransparent =
other.mEnsureNavigationBarContrastWhenTransparent;
if (other.mResizeMode != RESIZE_MODE_RESIZEABLE) {
mResizeMode = other.mResizeMode;
}
if (other.mMinWidth != -1) {
mMinWidth = other.mMinWidth;
}
if (other.mMinHeight != -1) {
mMinHeight = other.mMinHeight;
}
if (other.mColorBackgroundFloating != 0) {
mColorBackgroundFloating = other.mColorBackgroundFloating;
}
}
private TaskDescription(Parcel source) {
readFromParcel(source);
}
/**
* Sets the label for this task description.
* @hide
*/
public void setLabel(String label) {
mLabel = label;
}
/**
* Sets the primary color for this task description.
* @hide
*/
public void setPrimaryColor(int primaryColor) {
// Ensure that the given color is valid
if ((primaryColor != 0) && (Color.alpha(primaryColor) != 255)) {
throw new RuntimeException("A TaskDescription's primary color should be opaque");
}
mColorPrimary = primaryColor;
}
/**
* Sets the background color for this task description.
* @hide
*/
public void setBackgroundColor(int backgroundColor) {
// Ensure that the given color is valid
if ((backgroundColor != 0) && (Color.alpha(backgroundColor) != 255)) {
throw new RuntimeException("A TaskDescription's background color should be opaque");
}
mColorBackground = backgroundColor;
}
/**
* Sets the background color floating for this task description.
* @hide
*/
public void setBackgroundColorFloating(int backgroundColor) {
// Ensure that the given color is valid
if ((backgroundColor != 0) && (Color.alpha(backgroundColor) != 255)) {
throw new RuntimeException(
"A TaskDescription's background color floating should be opaque");
}
mColorBackgroundFloating = backgroundColor;
}
/**
* @hide
*/
public void setStatusBarColor(int statusBarColor) {
mStatusBarColor = statusBarColor;
}
/**
* @hide
*/
public void setNavigationBarColor(int navigationBarColor) {
mNavigationBarColor = navigationBarColor;
}
/**
* Sets the icon resource for this task description.
* @hide
*/
public void setIcon(Icon icon) {
mIcon = icon;
}
/**
* Moves the icon bitmap reference from an actual Bitmap to a file containing the
* bitmap.
* @hide
*/
public void setIconFilename(String iconFilename) {
mIconFilename = iconFilename;
if (iconFilename != null) {
// Only reset the icon if an actual persisted icon filepath was set
mIcon = null;
}
}
/**
* Sets the resize mode for this task description. Resize mode as in
* {@link android.content.pm.ActivityInfo}.
* @hide
*/
public void setResizeMode(int resizeMode) {
mResizeMode = resizeMode;
}
/**
* The minimal width size to show the app content in freeform mode.
* @param minWidth minimal width, -1 for system default.
* @hide
*/
public void setMinWidth(int minWidth) {
mMinWidth = minWidth;
}
/**
* The minimal height size to show the app content in freeform mode.
* @param minHeight minimal height, -1 for system default.
* @hide
*/
public void setMinHeight(int minHeight) {
mMinHeight = minHeight;
}
/**
* @return The label and description of the current state of this task.
*/
public String getLabel() {
return mLabel;
}
/**
* @return The actual icon that represents the current state of this task if it is in memory
* or loads it from disk if available.
* @hide
*/
public Icon loadIcon() {
if (mIcon != null) {
return mIcon;
}
Bitmap loadedIcon = loadTaskDescriptionIcon(mIconFilename, UserHandle.myUserId());
if (loadedIcon != null) {
return Icon.createWithBitmap(loadedIcon);
}
return null;
}
/**
* @return The in-memory or loaded icon that represents the current state of this task.
* @deprecated This call is no longer supported. The caller should keep track of any icons
* it sets for the task descriptions internally.
*/
@Deprecated
public Bitmap getIcon() {
Bitmap icon = getInMemoryIcon();
if (icon != null) {
return icon;
}
return loadTaskDescriptionIcon(mIconFilename, UserHandle.myUserId());
}
/** @hide */
@Nullable
public Icon getRawIcon() {
return mIcon;
}
/** @hide */
@TestApi
@Nullable
public String getIconResourcePackage() {
if (mIcon != null && mIcon.getType() == Icon.TYPE_RESOURCE) {
return mIcon.getResPackage();
}
return "";
}
/** @hide */
@TestApi
public int getIconResource() {
if (mIcon != null && mIcon.getType() == Icon.TYPE_RESOURCE) {
return mIcon.getResId();
}
return 0;
}
/** @hide */
@TestApi
public String getIconFilename() {
return mIconFilename;
}
/** @hide */
@UnsupportedAppUsage
public Bitmap getInMemoryIcon() {
if (mIcon != null && mIcon.getType() == Icon.TYPE_BITMAP) {
return mIcon.getBitmap();
}
return null;
}
/** @hide */
@UnsupportedAppUsage
public static Bitmap loadTaskDescriptionIcon(String iconFilename, int userId) {
if (iconFilename != null) {
try {
return getTaskService().getTaskDescriptionIcon(iconFilename,
userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return null;
}
/**
* @return The color override on the theme's primary color.
*/
@ColorInt
public int getPrimaryColor() {
return mColorPrimary;
}
/**
* @return The color override on the theme's background color.
*/
@ColorInt
public int getBackgroundColor() {
return mColorBackground;
}
/**
* @return The background color floating.
* @hide
*/
public int getBackgroundColorFloating() {
return mColorBackgroundFloating;
}
/**
* @return The color override on the theme's status bar color.
*/
@ColorInt
public int getStatusBarColor() {
return mStatusBarColor;
}
/**
* @return The color override on the theme's navigation bar color.
*/
@ColorInt
public int getNavigationBarColor() {
return mNavigationBarColor;
}
/**
* @hide
*/
public boolean getEnsureStatusBarContrastWhenTransparent() {
return mEnsureStatusBarContrastWhenTransparent;
}
/**
* @hide
*/
@Appearance
public int getSystemBarsAppearance() {
return mSystemBarsAppearance;
}
/**
* @hide
*/
public void setEnsureStatusBarContrastWhenTransparent(
boolean ensureStatusBarContrastWhenTransparent) {
mEnsureStatusBarContrastWhenTransparent = ensureStatusBarContrastWhenTransparent;
}
/**
* @hide
*/
public void setSystemBarsAppearance(@Appearance int systemBarsAppearance) {
mSystemBarsAppearance = systemBarsAppearance;
}
/**
* @hide
*/
public boolean getEnsureNavigationBarContrastWhenTransparent() {
return mEnsureNavigationBarContrastWhenTransparent;
}
/**
* @hide
*/
public void setEnsureNavigationBarContrastWhenTransparent(
boolean ensureNavigationBarContrastWhenTransparent) {
mEnsureNavigationBarContrastWhenTransparent =
ensureNavigationBarContrastWhenTransparent;
}
/**
* @hide
*/
public int getResizeMode() {
return mResizeMode;
}
/**
* @hide
*/
public int getMinWidth() {
return mMinWidth;
}
/**
* @hide
*/
public int getMinHeight() {
return mMinHeight;
}
/** @hide */
public void saveToXml(TypedXmlSerializer out) throws IOException {
if (mLabel != null) {
out.attribute(null, ATTR_TASKDESCRIPTIONLABEL, mLabel);
}
if (mColorPrimary != 0) {
out.attributeIntHex(null, ATTR_TASKDESCRIPTIONCOLOR_PRIMARY, mColorPrimary);
}
if (mColorBackground != 0) {
out.attributeIntHex(null, ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND, mColorBackground);
}
if (mColorBackgroundFloating != 0) {
out.attributeIntHex(null, ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND_FLOATING,
mColorBackgroundFloating);
}
if (mIconFilename != null) {
out.attribute(null, ATTR_TASKDESCRIPTIONICON_FILENAME, mIconFilename);
}
if (mIcon != null && mIcon.getType() == Icon.TYPE_RESOURCE) {
out.attributeInt(null, ATTR_TASKDESCRIPTIONICON_RESOURCE, mIcon.getResId());
out.attribute(null, ATTR_TASKDESCRIPTIONICON_RESOURCE_PACKAGE,
mIcon.getResPackage());
}
}
/** @hide */
public void restoreFromXml(TypedXmlPullParser in) {
final String label = in.getAttributeValue(null, ATTR_TASKDESCRIPTIONLABEL);
if (label != null) {
setLabel(label);
}
final int colorPrimary = in.getAttributeIntHex(null,
ATTR_TASKDESCRIPTIONCOLOR_PRIMARY, 0);
if (colorPrimary != 0) {
setPrimaryColor(colorPrimary);
}
final int colorBackground = in.getAttributeIntHex(null,
ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND, 0);
if (colorBackground != 0) {
setBackgroundColor(colorBackground);
}
final int colorBackgroundFloating = in.getAttributeIntHex(null,
ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND_FLOATING, 0);
if (colorBackgroundFloating != 0) {
setBackgroundColorFloating(colorBackgroundFloating);
}
final String iconFilename = in.getAttributeValue(null,
ATTR_TASKDESCRIPTIONICON_FILENAME);
if (iconFilename != null) {
setIconFilename(iconFilename);
}
final int iconResourceId = in.getAttributeInt(null,
ATTR_TASKDESCRIPTIONICON_RESOURCE, Resources.ID_NULL);
final String iconResourcePackage = in.getAttributeValue(null,
ATTR_TASKDESCRIPTIONICON_RESOURCE_PACKAGE);
if (iconResourceId != Resources.ID_NULL && iconResourcePackage != null) {
setIcon(Icon.createWithResource(iconResourcePackage,
iconResourceId));
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
if (mLabel == null) {
dest.writeInt(0);
} else {
dest.writeInt(1);
dest.writeString(mLabel);
}
final Bitmap bitmapIcon = getInMemoryIcon();
if (mIcon == null || (bitmapIcon != null && bitmapIcon.isRecycled())) {
// If there is no icon, or if the icon is a bitmap that has been recycled, then
// don't write anything to disk
dest.writeInt(0);
} else {
dest.writeInt(1);
mIcon.writeToParcel(dest, 0);
}
dest.writeInt(mColorPrimary);
dest.writeInt(mColorBackground);
dest.writeInt(mStatusBarColor);
dest.writeInt(mNavigationBarColor);
dest.writeInt(mSystemBarsAppearance);
dest.writeBoolean(mEnsureStatusBarContrastWhenTransparent);
dest.writeBoolean(mEnsureNavigationBarContrastWhenTransparent);
dest.writeInt(mResizeMode);
dest.writeInt(mMinWidth);
dest.writeInt(mMinHeight);
if (mIconFilename == null) {
dest.writeInt(0);
} else {
dest.writeInt(1);
dest.writeString(mIconFilename);
}
dest.writeInt(mColorBackgroundFloating);
}
public void readFromParcel(Parcel source) {
mLabel = source.readInt() > 0 ? source.readString() : null;
if (source.readInt() > 0) {
mIcon = Icon.CREATOR.createFromParcel(source);
}
mColorPrimary = source.readInt();
mColorBackground = source.readInt();
mStatusBarColor = source.readInt();
mNavigationBarColor = source.readInt();
mSystemBarsAppearance = source.readInt();
mEnsureStatusBarContrastWhenTransparent = source.readBoolean();
mEnsureNavigationBarContrastWhenTransparent = source.readBoolean();
mResizeMode = source.readInt();
mMinWidth = source.readInt();
mMinHeight = source.readInt();
mIconFilename = source.readInt() > 0 ? source.readString() : null;
mColorBackgroundFloating = source.readInt();
}
public static final @android.annotation.NonNull Creator
* noteAppRestrictionEnabled(
* "com.example.app",
* appUid,
* RESTRICTION_LEVEL_FORCE_STOPPED,
* true,
* RESTRICTION_REASON_USER,
* "settings",
* 0);
*
* Example arguments when app is put in restricted standby bucket for exceeding X hours of jobs:
*
* noteAppRestrictionEnabled(
* "com.example.app",
* appUid,
* RESTRICTION_LEVEL_RESTRICTED_BUCKET,
* true,
* RESTRICTION_REASON_SYSTEM_HEALTH,
* "job_duration",
* X * 3600 * 1000L);
*
*
* @param packageName the package name of the app
* @param uid the uid of the app
* @param restrictionLevel the restriction level specified in {@code RestrictionLevel}
* @param enabled whether the state is being applied or removed
* @param reason the reason for the restriction state change, from {@code RestrictionReason}
* @param subReason a string sub reason limited to 16 characters that specifies additional
* information about the reason for restriction. This string must only contain
* reasons related to excessive system resource usage or in some cases,
* source of the restriction. This string must not contain any details that
* identify user behavior beyond their actions to restrict/unrestrict/launch
* apps in some way.
* Examples of system resource usage: wakelock, wakeups, mobile_data,
* binder_calls, memory, excessive_threads, excessive_cpu, gps_scans, etc.
* Examples of user actions: settings, notification, command_line, launch, etc.
*
* @param threshold for reasons that are due to exceeding some threshold, the threshold value
* must be specified. The unit of the threshold depends on the reason and/or
* subReason. For time, use milliseconds. For memory, use KB. For count, use
* the actual count or if rate limited, normalized per-hour. For power,
* use milliwatts. For CPU, use mcycles.
*
* @hide
*/
@RequiresPermission(Manifest.permission.DEVICE_POWER)
public void noteAppRestrictionEnabled(@NonNull String packageName, int uid,
@RestrictionLevel int restrictionLevel, boolean enabled,
@RestrictionReason int reason,
@Nullable String subReason, long threshold) {
try {
getService().noteAppRestrictionEnabled(packageName, uid, restrictionLevel, enabled,
reason, subReason, threshold);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Notifies {@link #getRunningAppProcesses app processes} that the system properties
* have changed.
*
* @see SystemProperties#addChangeCallback
*
* @hide
*/
@TestApi
public void notifySystemPropertiesChanged() {
// Note: this cannot use {@link ServiceManager#listServices()} to notify all the services,
// as that is not available from tests.
final var binder = ActivityManager.getService().asBinder();
if (binder != null) {
var data = Parcel.obtain();
try {
binder.transact(IBinder.SYSPROPS_TRANSACTION, data, null /* reply */,
0 /* flags */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
data.recycle();
}
}
/**
* A subset of immutable pending intent information suitable for caching on the client side.
*
* @hide
*/
public static final class PendingIntentInfo implements Parcelable {
@Nullable private final String mCreatorPackage;
private final int mCreatorUid;
private final boolean mImmutable;
private final int mIntentSenderType;
public PendingIntentInfo(@Nullable String creatorPackage, int creatorUid, boolean immutable,
int intentSenderType) {
mCreatorPackage = creatorPackage;
mCreatorUid = creatorUid;
mImmutable = immutable;
mIntentSenderType = intentSenderType;
}
@Nullable
public String getCreatorPackage() {
return mCreatorPackage;
}
public int getCreatorUid() {
return mCreatorUid;
}
public boolean isImmutable() {
return mImmutable;
}
public int getIntentSenderType() {
return mIntentSenderType;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeString(mCreatorPackage);
parcel.writeInt(mCreatorUid);
parcel.writeBoolean(mImmutable);
parcel.writeInt(mIntentSenderType);
}
public static final @NonNull Creator