Merge "[automerger skipped] Merge "Import translations. DO NOT MERGE" into cw-f-dev am: d6df52e22f -s ours skipped: 7f649e7e6d am: 5cd687505a -s ours am: 77803cc4fa -s ours am: 4f65db7421 -s ours am: b98b5de9f3 -s ours"
diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp
index 519852d..cdec6a0 100644
--- a/cmds/incident/main.cpp
+++ b/cmds/incident/main.cpp
@@ -148,9 +148,19 @@
static int
get_dest(const char* arg)
{
- if (strcmp(arg, "LOCAL") == 0) return 0;
- if (strcmp(arg, "EXPLICIT") == 0) return 1;
- if (strcmp(arg, "AUTOMATIC") == 0) return 2;
+ if (strcmp(arg, "L") == 0
+ || strcmp(arg, "LOCAL") == 0) {
+ return DEST_LOCAL;
+ }
+ if (strcmp(arg, "E") == 0
+ || strcmp(arg, "EXPLICIT") == 0) {
+ return DEST_EXPLICIT;
+ }
+ if (strcmp(arg, "A") == 0
+ || strcmp(arg, "AUTO") == 0
+ || strcmp(arg, "AUTOMATIC") == 0) {
+ return DEST_AUTOMATIC;
+ }
return -1; // return the default value
}
diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp
index 5db2239..44adaec 100644
--- a/cmds/incidentd/src/Privacy.cpp
+++ b/cmds/incidentd/src/Privacy.cpp
@@ -67,8 +67,14 @@
PrivacySpec new_spec_from_args(int dest)
{
- if (dest < 0) return PrivacySpec();
- return PrivacySpec(dest);
+ switch (dest) {
+ case android::os::DEST_AUTOMATIC:
+ case android::os::DEST_EXPLICIT:
+ case android::os::DEST_LOCAL:
+ return PrivacySpec(dest);
+ default:
+ return PrivacySpec();
+ }
}
PrivacySpec get_default_dropbox_spec() { return PrivacySpec(android::os::DEST_AUTOMATIC); }
\ No newline at end of file
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 998ac5f..c34f4d9 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -16,6 +16,8 @@
package android.app;
+import android.app.ActivityThread.ActivityClientRecord;
+import android.app.servertransaction.PendingTransactionActions;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Binder;
@@ -141,6 +143,21 @@
}
r.window = r.activity.getWindow();
r.instanceState = null;
+
+ final ActivityClientRecord clientRecord = mActivityThread.getActivityClient(r);
+ final PendingTransactionActions pendingActions;
+
+ if (!r.activity.mFinished) {
+ // This matches pending actions set in ActivityThread#handleLaunchActivity
+ pendingActions = new PendingTransactionActions();
+ pendingActions.setOldState(clientRecord.state);
+ pendingActions.setRestoreInstanceState(true);
+ pendingActions.setCallOnPostCreate(true);
+ } else {
+ pendingActions = null;
+ }
+
+ mActivityThread.handleStartActivity(clientRecord, pendingActions);
r.curState = STARTED;
if (desiredState == RESUMED) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 746a090..f6697e8 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -602,6 +602,13 @@
*/
public static final int PRIVATE_FLAG_VENDOR = 1 << 18;
+ /**
+ * Value for {@linl #privateFlags}: whether this app is pre-installed on the
+ * product partition of the system image.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
+
/** @hide */
@IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -619,6 +626,7 @@
PRIVATE_FLAG_OEM,
PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE,
PRIVATE_FLAG_PRIVILEGED,
+ PRIVATE_FLAG_PRODUCT,
PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
PRIVATE_FLAG_VENDOR,
@@ -1699,6 +1707,11 @@
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
+ /** @hide */
+ public boolean isProduct() {
+ return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
+ }
+
/**
* Returns whether or not this application was installed as a virtual preload.
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 3bb812b..d5c88aa 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6393,6 +6393,11 @@
}
/** @hide */
+ public boolean isProduct() {
+ return applicationInfo.isProduct();
+ }
+
+ /** @hide */
public boolean isPrivileged() {
return applicationInfo.isPrivilegedApp();
}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 158041d..03203d0 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -41,6 +41,7 @@
private static final String ENV_OEM_ROOT = "OEM_ROOT";
private static final String ENV_ODM_ROOT = "ODM_ROOT";
private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
+ private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT";
/** {@hide} */
public static final String DIR_ANDROID = "Android";
@@ -62,6 +63,7 @@
private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
+ private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product");
private static UserEnvironment sCurrentUser;
private static boolean sUserRequired;
@@ -180,6 +182,16 @@
}
/**
+ * Return root directory of the "product" partition holding product-specific
+ * customizations if any. If present, the partition is mounted read-only.
+ *
+ * @hide
+ */
+ public static File getProductDirectory() {
+ return DIR_PRODUCT_ROOT;
+ }
+
+ /**
* Return the system directory for a user. This is for use by system
* services to store files relating to the user. This directory will be
* automatically deleted when the user is removed.
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index c5af897..111934f 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -149,6 +149,9 @@
final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
+ final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
+ final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
+
final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
public static SystemConfig getInstance() {
@@ -240,6 +243,14 @@
return mVendorPrivAppDenyPermissions.get(packageName);
}
+ public ArraySet<String> getProductPrivAppPermissions(String packageName) {
+ return mProductPrivAppPermissions.get(packageName);
+ }
+
+ public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
+ return mProductPrivAppDenyPermissions.get(packageName);
+ }
+
public Map<String, Boolean> getOemPermissions(String packageName) {
final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
if (oemPermissions != null) {
@@ -278,6 +289,14 @@
Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
+
+ // Allow Product to customize system configs around libs, features, permissions and apps
+ int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
+ ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+ readPermissions(Environment.buildPath(
+ Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
+ readPermissions(Environment.buildPath(
+ Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
}
void readPermissions(File libraryDir, int permissionFlag) {
@@ -598,15 +617,20 @@
}
XmlUtils.skipCurrentTag(parser);
} else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
- // privapp permissions from system and vendor partitions are stored
+ // privapp permissions from system, vendor and product partitions are stored
// separately. This is to prevent xml files in the vendor partition from
// granting permissions to priv apps in the system partition and vice
// versa.
boolean vendor = permFile.toPath().startsWith(
Environment.getVendorDirectory().toPath());
+ boolean product = permFile.toPath().startsWith(
+ Environment.getProductDirectory().toPath());
if (vendor) {
readPrivAppPermissions(parser, mVendorPrivAppPermissions,
mVendorPrivAppDenyPermissions);
+ } else if (product) {
+ readPrivAppPermissions(parser, mProductPrivAppPermissions,
+ mProductPrivAppDenyPermissions);
} else {
readPrivAppPermissions(parser, mPrivAppPermissions,
mPrivAppDenyPermissions);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 403937b..7e17a49 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -174,6 +174,10 @@
argv[argc++] = AssetManager::OVERLAY_DIR;
}
+ if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
+ argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
+ }
+
// Finally, invoke idmap (if any overlay directory exists)
if (argc > 5) {
execv(AssetManager::IDMAP_BIN, (char* const*)argv);
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 956b724..3b7b14c 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -85,11 +85,15 @@
static const char* kOverlayDir = "/system/vendor/overlay/";
static const char* kVendorOverlayDir = "/vendor/overlay";
static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
+ static const char* kSystemProductOverlayDir = "/system/product/overlay/";
+ static const char* kProductOverlayDir = "/product/overlay";
static const char* kApkSuffix = ".apk";
if ((android::base::StartsWith(path, kOverlayDir)
|| android::base::StartsWith(path, kOverlaySubdir)
- || android::base::StartsWith(path, kVendorOverlayDir))
+ || android::base::StartsWith(path, kVendorOverlayDir)
+ || android::base::StartsWith(path, kSystemProductOverlayDir)
+ || android::base::StartsWith(path, kProductOverlayDir))
&& android::base::EndsWith(path, kApkSuffix)
&& path.find("/../") == std::string::npos) {
return true;
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 0485625..a5698af 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -73,6 +73,7 @@
const char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
+const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
const char* AssetManager::TARGET_PACKAGE_NAME = "android";
const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index ecc5dc1..08da731 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -60,6 +60,7 @@
static const char* RESOURCES_FILENAME;
static const char* IDMAP_BIN;
static const char* OVERLAY_DIR;
+ static const char* PRODUCT_OVERLAY_DIR;
/*
* If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
* APKs in OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index 983ca75..dcd4dce 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -47,11 +47,16 @@
private SoundPool mSoundPool;
private SoundState[] mSounds;
+ private static final String[] SOUND_DIRS = {
+ "/product/media/audio/ui/",
+ "/system/media/audio/ui/",
+ };
+
private static final String[] SOUND_FILES = {
- "/system/media/audio/ui/camera_click.ogg",
- "/system/media/audio/ui/camera_focus.ogg",
- "/system/media/audio/ui/VideoRecord.ogg",
- "/system/media/audio/ui/VideoStop.ogg"
+ "camera_click.ogg",
+ "camera_focus.ogg",
+ "VideoRecord.ogg",
+ "VideoStop.ogg"
};
private static final String TAG = "MediaActionSound";
@@ -132,12 +137,16 @@
}
private int loadSound(SoundState sound) {
- int id = mSoundPool.load(SOUND_FILES[sound.name], 1);
- if (id > 0) {
- sound.state = STATE_LOADING;
- sound.id = id;
+ final String soundFileName = SOUND_FILES[sound.name];
+ for (String soundDir : SOUND_DIRS) {
+ int id = mSoundPool.load(soundDir + soundFileName, 1);
+ if (id > 0) {
+ sound.state = STATE_LOADING;
+ sound.id = id;
+ return id;
+ }
}
- return id;
+ return 0;
}
/**
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index cb4e46f..c309038 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -158,6 +158,7 @@
public static final String SCANNED_BUILD_PREFS_NAME = "MediaScanBuild";
public static final String LAST_INTERNAL_SCAN_FINGERPRINT = "lastScanFingerprint";
private static final String SYSTEM_SOUNDS_DIR = "/system/media/audio";
+ private static final String PRODUCT_SOUNDS_DIR = "/product/media/audio";
private static String sLastInternalScanFingerprint;
private static final String[] ID3_GENRES = {
@@ -1153,7 +1154,10 @@
private static boolean isSystemSoundWithMetadata(String path) {
if (path.startsWith(SYSTEM_SOUNDS_DIR + ALARMS_DIR)
|| path.startsWith(SYSTEM_SOUNDS_DIR + RINGTONES_DIR)
- || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)) {
+ || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)
+ || path.startsWith(PRODUCT_SOUNDS_DIR + ALARMS_DIR)
+ || path.startsWith(PRODUCT_SOUNDS_DIR + RINGTONES_DIR)
+ || path.startsWith(PRODUCT_SOUNDS_DIR + NOTIFICATIONS_DIR)) {
return true;
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 1056ecc..b3f68d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1472,7 +1472,6 @@
return mPrivateLayout.getActiveRemoteInputText();
}
-
public void animateTranslateNotification(final float leftTarget) {
if (mTranslateAnim != null) {
mTranslateAnim.cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 8336d29..907af69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.graphics.Matrix;
import android.graphics.Rect;
@@ -35,10 +36,11 @@
import com.android.systemui.Interpolators;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationListContainer;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowView;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.function.Consumer;
@@ -57,16 +59,17 @@
private final NotificationPanelView mNotificationPanel;
private final NotificationListContainer mNotificationContainer;
private final StatusBarWindowView mStatusBarWindow;
- private final Consumer<Boolean> mPanelCollapser;
+ private final StatusBar mStatusBar;
+ private boolean mAnimationPending;
public ActivityLaunchAnimator(StatusBarWindowView statusBarWindow,
- Consumer<Boolean> panelCollapser,
+ StatusBar statusBar,
NotificationPanelView notificationPanel,
NotificationListContainer container) {
mNotificationPanel = notificationPanel;
mNotificationContainer = container;
mStatusBarWindow = statusBarWindow;
- mPanelCollapser = panelCollapser;
+ mStatusBar = statusBar;
}
public ActivityOptions getLaunchAnimation(
@@ -76,6 +79,21 @@
new RemoteAnimationAdapter(animationRunner, 1000 /* Duration */, 0 /* delay */));
}
+ public boolean isAnimationPending() {
+ return mAnimationPending;
+ }
+
+ public void setLaunchResult(int launchResult) {
+ setAnimationPending((launchResult == ActivityManager.START_TASK_TO_FRONT
+ || launchResult == ActivityManager.START_SUCCESS)
+ && mStatusBar.getBarState() == StatusBarState.SHADE);
+ }
+
+ private void setAnimationPending(boolean pending) {
+ mAnimationPending = pending;
+ mStatusBarWindow.setExpandAnimationPending(pending);
+ }
+
class AnimationRunner extends IRemoteAnimationRunner.Stub {
private final ExpandableNotificationRow mSourceNotification;
@@ -94,7 +112,6 @@
IRemoteAnimationFinishedCallback iRemoteAnimationFinishedCallback)
throws RemoteException {
mSourceNotification.post(() -> {
- boolean first = true;
for (RemoteAnimationTarget app : remoteAnimationTargets) {
if (app.mode == RemoteAnimationTarget.MODE_OPENING) {
setExpandAnimationRunning(true);
@@ -139,7 +156,7 @@
public void onAnimationEnd(Animator animation) {
setExpandAnimationRunning(false);
if (mInstantCollapsePanel) {
- mPanelCollapser.accept(false /* animate */);
+ mStatusBar.collapsePanel(false /* animate */);
}
try {
iRemoteAnimationFinishedCallback.onAnimationFinished();
@@ -152,6 +169,7 @@
break;
}
}
+ setAnimationPending(false);
});
}
@@ -198,6 +216,10 @@
@Override
public void onAnimationCancelled() throws RemoteException {
+ mSourceNotification.post(() -> {
+ setAnimationPending(false);
+ mStatusBar.onLaunchAnimationCancelled();
+ });
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index a62a424..2b7e474 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -950,7 +950,7 @@
}
public boolean isCollapsing() {
- return mClosing;
+ return mClosing || mLaunchingNotification;
}
public boolean isTracking() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 7d84550..b519824 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -100,7 +100,6 @@
import android.service.notification.StatusBarNotification;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
-import android.text.SpannedString;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -589,7 +588,7 @@
private NavigationBarFragment mNavigationBar;
private View mNavigationBarView;
- private ActivityLaunchAnimator mActivityLaunchAnimator;
+ protected ActivityLaunchAnimator mActivityLaunchAnimator;
@Override
public void start() {
@@ -760,7 +759,7 @@
mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
mActivityLaunchAnimator = new ActivityLaunchAnimator(mStatusBarWindow,
- this::collapsePanel,
+ this,
mNotificationPanel,
mStackScroller);
mGutsManager.setUpWithPresenter(this, mEntryManager, mStackScroller, mCheckSaveListener,
@@ -2054,6 +2053,12 @@
}
}
+ public void onLaunchAnimationCancelled() {
+ if (!isCollapsing()) {
+ onClosingFinished();
+ }
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -3418,7 +3423,7 @@
}
public boolean isCollapsing() {
- return mNotificationPanel.isCollapsing();
+ return mNotificationPanel.isCollapsing() || mActivityLaunchAnimator.isAnimationPending();
}
public void addPostCollapseAction(Runnable r) {
@@ -4959,6 +4964,7 @@
try {
launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
null, null, getActivityOptions(row));
+ mActivityLaunchAnimator.setLaunchResult(launchResult);
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here.
// Just log the exception message.
@@ -4970,7 +4976,7 @@
mAssistManager.hideAssist();
}
}
- if (shouldCollapse(launchResult)) {
+ if (shouldCollapse()) {
if (Looper.getMainLooper().isCurrentThread()) {
collapsePanel();
} else {
@@ -5003,17 +5009,8 @@
}, afterKeyguardGone);
}
- private boolean shouldCollapse(int launchResult) {
- return mState != StatusBarState.SHADE
- || (launchResult != ActivityManager.START_TASK_TO_FRONT
- && launchResult != ActivityManager.START_SUCCESS);
- }
-
- public void onExpandAnimationFinished() {
- if (!isPresenterFullyCollapsed()) {
- instantCollapseNotificationPanel();
- visibilityChanged(false);
- }
+ private boolean shouldCollapse() {
+ return mState != StatusBarState.SHADE || !mActivityLaunchAnimator.isAnimationPending();
}
public void collapsePanel(boolean animate) {
@@ -5128,7 +5125,8 @@
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(row),
new UserHandle(UserHandle.getUserId(appUid)));
- if (shouldCollapse(launchResult)) {
+ mActivityLaunchAnimator.setLaunchResult(launchResult);
+ if (shouldCollapse()) {
// Putting it back on the main thread, since we're touching views
mStatusBarWindow.post(() -> animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index f7d0967..e32914f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -89,6 +89,7 @@
private boolean mTouchCancelled;
private boolean mTouchActive;
private boolean mExpandAnimationRunning;
+ private boolean mExpandAnimationPending;
public StatusBarWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -268,7 +269,7 @@
|| ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
setTouchActive(false);
}
- if (mTouchCancelled || mExpandAnimationRunning) {
+ if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
return false;
}
mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
@@ -393,6 +394,10 @@
mExpandAnimationRunning = expandAnimationRunning;
}
+ public void setExpandAnimationPending(boolean pending) {
+ mExpandAnimationPending = pending;
+ }
+
public class LayoutParams extends FrameLayout.LayoutParams {
public boolean ignoreRightInset;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 1e894ff..3febdfd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -119,7 +119,8 @@
// for the current foreground user.
LocationManager locationManager =
(LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
- return locationManager.isLocationEnabledForUser(Process.myUserHandle());
+ return locationManager.isLocationEnabledForUser(
+ UserHandle.of(ActivityManager.getCurrentUser()));
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 99202f4..bdf9b1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -84,6 +84,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -188,7 +189,8 @@
mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
mPowerManager, mNotificationPanelView, mBarService, mNotificationListener,
mNotificationLogger, mVisualStabilityManager, mViewHierarchyManager,
- mEntryManager, mScrimController, mFingerprintUnlockController);
+ mEntryManager, mScrimController, mFingerprintUnlockController,
+ mock(ActivityLaunchAnimator.class));
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mContext.getComponents();
mEntryManager.setUpForTest(mStatusBar, mStackScroller, mStatusBar, mHeadsUpManager,
@@ -593,7 +595,8 @@
VisualStabilityManager visualStabilityManager,
NotificationViewHierarchyManager viewHierarchyManager,
TestableNotificationEntryManager entryManager, ScrimController scrimController,
- FingerprintUnlockController fingerprintUnlockController) {
+ FingerprintUnlockController fingerprintUnlockController,
+ ActivityLaunchAnimator launchAnimator) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
mKeyguardIndicationController = key;
@@ -610,6 +613,7 @@
mEntryManager = entryManager;
mScrimController = scrimController;
mFingerprintUnlockController = fingerprintUnlockController;
+ mActivityLaunchAnimator = launchAnimator;
}
private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index bd93b179..1dd92f3 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1577,13 +1577,22 @@
}
/**
- * Returns all providers by name, including passive, but excluding
- * fused, also including ones that are not permitted to
- * be accessed by the calling activity or are currently disabled.
+ * Returns all providers by name, including passive and the ones that are not permitted to
+ * be accessed by the calling activity or are currently disabled, but excluding fused.
*/
@Override
public List<String> getAllProviders() {
- List<String> out = getProviders(null /*criteria*/, false /*enabledOnly*/);
+ ArrayList<String> out;
+ synchronized (mLock) {
+ out = new ArrayList<>(mProviders.size());
+ for (LocationProviderInterface provider : mProviders) {
+ String name = provider.getName();
+ if (LocationManager.FUSED_PROVIDER.equals(name)) {
+ continue;
+ }
+ out.add(name);
+ }
+ }
if (D) Log.d(TAG, "getAllProviders()=" + out);
return out;
}
@@ -2586,9 +2595,10 @@
// Check INTERACT_ACROSS_USERS permission if userId is not current user id.
checkInteractAcrossUsersPermission(userId);
- // Enable or disable all location providers
+ // Enable or disable all location providers. Fused provider and passive provider are
+ // excluded.
synchronized (mLock) {
- for(String provider : getAllProviders()) {
+ for(String provider : getAllProvidersForLocationSettings()) {
setProviderEnabledForUser(provider, enabled, userId);
}
}
@@ -2605,9 +2615,10 @@
// Check INTERACT_ACROSS_USERS permission if userId is not current user id.
checkInteractAcrossUsersPermission(userId);
- // If at least one location provider is enabled, return true
+ // If at least one location provider is enabled, return true. Fused provider and passive
+ // provider are excluded.
synchronized (mLock) {
- for (String provider : getAllProviders()) {
+ for (String provider : getAllProvidersForLocationSettings()) {
if (isProviderEnabledForUser(provider, userId)) {
return true;
}
@@ -2691,6 +2702,26 @@
}
/**
+ * Return all location providers except fused provider and passive provider. These two
+ * providers are not generating location by themselves, but only echo locations from other
+ * providers.
+ *
+ * @return All location providers except fused provider and passive provider, including
+ * providers that are not permitted to be accessed by the calling activity or are
+ * currently disabled.
+ */
+ private List<String> getAllProvidersForLocationSettings() {
+ List<String> providersForSettings = new ArrayList<>(mProviders.size());
+ for (String provider : getAllProviders()) {
+ if (provider.equals(LocationManager.PASSIVE_PROVIDER)) {
+ continue;
+ }
+ providersForSettings.add(provider);
+ }
+ return providersForSettings;
+ }
+
+ /**
* Read location provider status from Settings.Secure
*
* @param provider the location provider to query
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index bedf0431..edeee3e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -133,6 +133,7 @@
import org.xmlpull.v1.XmlPullParserException;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
@@ -4767,6 +4768,16 @@
Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
}
+ private String getSoundEffectFilePath(int effectType) {
+ String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
+ + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
+ if (!new File(filePath).isFile()) {
+ filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
+ + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
+ }
+ return filePath;
+ }
+
private boolean onLoadSoundEffects() {
int status;
@@ -4836,9 +4847,7 @@
continue;
}
if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
- String filePath = Environment.getRootDirectory()
- + SOUND_EFFECTS_PATH
- + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
+ String filePath = getSoundEffectFilePath(effect);
int sampleId = mSoundPool.load(filePath, 0);
if (sampleId <= 0) {
Log.w(TAG, "Soundpool could not load file: "+filePath);
@@ -4944,8 +4953,7 @@
} else {
MediaPlayer mediaPlayer = new MediaPlayer();
try {
- String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
- SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
+ String filePath = getSoundEffectFilePath(effectType);
mediaPlayer.setDataSource(filePath);
mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
mediaPlayer.prepare();
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 5bf38dc..10e05cf 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -362,9 +362,10 @@
continue;
}
- // If the path is in /system or /vendor, ignore. It will have been ota-dexopted into
- // /data/ota and moved into the dalvik-cache already.
- if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")) {
+ // If the path is in /system, /vendor or /product, ignore. It will have been
+ // ota-dexopted into /data/ota and moved into the dalvik-cache already.
+ if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")
+ || pkg.codePath.startsWith("/product")) {
continue;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 837a118..7767945 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -466,6 +466,7 @@
static final int SCAN_AS_PRIVILEGED = 1<<18;
static final int SCAN_AS_OEM = 1<<19;
static final int SCAN_AS_VENDOR = 1<<20;
+ static final int SCAN_AS_PRODUCT = 1<<21;
@IntDef(flag = true, prefix = { "SCAN_" }, value = {
SCAN_NO_DEX,
@@ -570,6 +571,8 @@
private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
+ private static final String PRODUCT_OVERLAY_DIR = "/product/overlay";
+
private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB = "pm.dexopt.priv-apps-oob";
/** Canonical intent used to identify what counts as a "web browser" app */
@@ -2552,7 +2555,7 @@
scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}
- // Collect vendor overlay packages. (Do this before scanning any apps.)
+ // Collect vendor/product overlay packages. (Do this before scanning any apps.)
// For security and version matching reason, only consider
// overlay packages if they reside in the right directory.
scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
@@ -2562,6 +2565,13 @@
| SCAN_AS_SYSTEM
| SCAN_AS_VENDOR,
0);
+ scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT,
+ 0);
mParallelPackageParserCallback.findStaticOverlayPackages();
@@ -2595,8 +2605,7 @@
0);
// Collected privileged vendor packages.
- File privilegedVendorAppDir = new File(Environment.getVendorDirectory(),
- "priv-app");
+ File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
try {
privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
} catch (IOException e) {
@@ -2636,6 +2645,37 @@
| SCAN_AS_OEM,
0);
+ // Collected privileged product packages.
+ File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
+ try {
+ privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(privilegedProductAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT
+ | SCAN_AS_PRIVILEGED,
+ 0);
+
+ // Collect ordinary product packages.
+ File productAppDir = new File(Environment.getProductDirectory(), "app");
+ try {
+ productAppDir = productAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
+ scanDirTracedLI(productAppDir,
+ mDefParseFlags
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT,
+ 0);
+
// Prune any system packages that no longer exist.
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
// Stub packages must either be replaced with full versions in the /data
@@ -2842,6 +2882,23 @@
scanFlags
| SCAN_AS_SYSTEM
| SCAN_AS_OEM;
+ } else if (FileUtils.contains(privilegedProductAppDir, scanFile)) {
+ reparseFlags =
+ mDefParseFlags |
+ PackageParser.PARSE_IS_SYSTEM_DIR;
+ rescanFlags =
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT
+ | SCAN_AS_PRIVILEGED;
+ } else if (FileUtils.contains(productAppDir, scanFile)) {
+ reparseFlags =
+ mDefParseFlags |
+ PackageParser.PARSE_IS_SYSTEM_DIR;
+ rescanFlags =
+ scanFlags
+ | SCAN_AS_SYSTEM
+ | SCAN_AS_PRODUCT;
} else {
Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
continue;
@@ -9862,6 +9919,7 @@
* <li>{@link #SCAN_AS_PRIVILEGED}</li>
* <li>{@link #SCAN_AS_OEM}</li>
* <li>{@link #SCAN_AS_VENDOR}</li>
+ * <li>{@link #SCAN_AS_PRODUCT}</li>
* <li>{@link #SCAN_AS_INSTANT_APP}</li>
* <li>{@link #SCAN_AS_VIRTUAL_PRELOAD}</li>
* </ul>
@@ -9884,6 +9942,10 @@
& ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0) {
scanFlags |= SCAN_AS_VENDOR;
}
+ if ((disabledPkgSetting.pkgPrivateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) {
+ scanFlags |= SCAN_AS_PRODUCT;
+ }
}
if (pkgSetting != null) {
final int userId = ((user == null) ? 0 : user.getIdentifier());
@@ -10662,6 +10724,10 @@
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VENDOR;
}
+ if ((scanFlags & SCAN_AS_PRODUCT) != 0) {
+ pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT;
+ }
+
if (!isSystemApp(pkg)) {
// Only system apps can use these features.
pkg.mOriginalPackages = null;
@@ -11708,6 +11774,8 @@
codeRoot = Environment.getOemDirectory();
} else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
codeRoot = Environment.getVendorDirectory();
+ } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) {
+ codeRoot = Environment.getProductDirectory();
} else {
// Unrecognized code path; take its top real segment as the apk root:
// e.g. /something/app/blah.apk => /something
@@ -16110,7 +16178,7 @@
boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
- // Set the system/privileged/oem/vendor flags as needed
+ // Set the system/privileged/oem/vendor/product flags as needed
final boolean privileged =
(oldPackage.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
@@ -16120,12 +16188,16 @@
final boolean vendor =
(oldPackage.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
+ final boolean product =
+ (oldPackage.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
final @ParseFlags int systemParseFlags = parseFlags;
final @ScanFlags int systemScanFlags = scanFlags
| SCAN_AS_SYSTEM
| (privileged ? SCAN_AS_PRIVILEGED : 0)
| (oem ? SCAN_AS_OEM : 0)
- | (vendor ? SCAN_AS_VENDOR : 0);
+ | (vendor ? SCAN_AS_VENDOR : 0)
+ | (product ? SCAN_AS_PRODUCT : 0);
replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags,
user, allUsers, installerPackageName, res, installReason);
@@ -17373,6 +17445,10 @@
return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
+ private static boolean isProductApp(PackageParser.Package pkg) {
+ return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
+ }
+
private static boolean hasDomainURLs(PackageParser.Package pkg) {
return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
}
@@ -18112,8 +18188,10 @@
try {
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
+ final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
return path.startsWith(privilegedAppDir.getCanonicalPath())
- || path.startsWith(privilegedVendorAppDir.getCanonicalPath());
+ || path.startsWith(privilegedVendorAppDir.getCanonicalPath())
+ || path.startsWith(privilegedProductAppDir.getCanonicalPath());
} catch (IOException e) {
Slog.e(TAG, "Unable to access code path " + path);
}
@@ -18138,6 +18216,15 @@
return false;
}
+ static boolean locationIsProduct(String path) {
+ try {
+ return path.startsWith(Environment.getProductDirectory().getCanonicalPath());
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to access code path " + path);
+ }
+ return false;
+ }
+
/*
* Tries to delete system package.
*/
@@ -18262,6 +18349,9 @@
if (locationIsVendor(codePathString)) {
scanFlags |= SCAN_AS_VENDOR;
}
+ if (locationIsProduct(codePathString)) {
+ scanFlags |= SCAN_AS_PRODUCT;
+ }
final File codePath = new File(codePathString);
final PackageParser.Package pkg =
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 47cd813..686c4a5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1555,6 +1555,15 @@
}
}
+ private boolean isProductApp(String pkg) {
+ try {
+ final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
+ return info != null && info.applicationInfo.isProduct();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
private int runGetPrivappPermissions() {
final String pkg = getNextArg();
if (pkg == null) {
@@ -1562,9 +1571,14 @@
return 1;
}
- ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
- SystemConfig.getInstance().getVendorPrivAppPermissions(pkg)
- : SystemConfig.getInstance().getPrivAppPermissions(pkg);
+ ArraySet<String> privAppPermissions = null;
+ if (isVendorApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
+ } else if (isProductApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
+ } else {
+ privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
+ }
getOutPrintWriter().println(privAppPermissions == null
? "{}" : privAppPermissions.toString());
@@ -1578,9 +1592,14 @@
return 1;
}
- ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
- SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg)
- : SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
+ ArraySet<String> privAppPermissions = null;
+ if (isVendorApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
+ } else if (isProductApp(pkg)) {
+ privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
+ } else {
+ privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
+ }
getOutPrintWriter().println(privAppPermissions == null
? "{}" : privAppPermissions.toString());
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 2a2430c..3e2bd4a 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -173,6 +173,10 @@
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
+ public boolean isProduct() {
+ return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
+ }
+
public boolean isForwardLocked() {
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
}
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 46ba006..7c92045 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -62,6 +62,7 @@
& (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
| ApplicationInfo.PRIVATE_FLAG_OEM
| ApplicationInfo.PRIVATE_FLAG_VENDOR
+ | ApplicationInfo.PRIVATE_FLAG_PRODUCT
| ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK
| ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8ce412e..5e9019d 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -851,6 +851,8 @@
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM;
pkgSetting.pkgPrivateFlags |=
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR;
+ pkgSetting.pkgPrivateFlags |=
+ pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT;
pkgSetting.primaryCpuAbiString = primaryCpuAbi;
pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
if (childPkgNames != null) {
@@ -4397,6 +4399,7 @@
ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY",
ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR",
+ ApplicationInfo.PRIVATE_FLAG_PRODUCT, "PRODUCT",
ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",
};
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 6e07eaa..e2123c2 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1215,6 +1215,10 @@
if (dir.isDirectory() && dir.canRead()) {
Collections.addAll(ret, dir.listFiles());
}
+ dir = new File(Environment.getProductDirectory(), "etc/default-permissions");
+ if (dir.isDirectory() && dir.canRead()) {
+ Collections.addAll(ret, dir.listFiles());
+ }
return ret.isEmpty() ? null : ret.toArray(new File[0]);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 786b998..cb3b107 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -954,9 +954,16 @@
* <p>This handles parent/child apps.
*/
private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) {
- ArraySet<String> wlPermissions = pkg.isVendor() ?
- SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName)
- : SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
+ ArraySet<String> wlPermissions = null;
+ if (pkg.isVendor()) {
+ wlPermissions =
+ SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName);
+ } else if (pkg.isProduct()) {
+ wlPermissions =
+ SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName);
+ } else {
+ wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
+ }
// Let's check if this package is whitelisted...
boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm);
// If it's not, we'll also tail-recurse to the parent.
@@ -979,11 +986,17 @@
// Only report violations for apps on system image
if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
// it's only a reportable violation if the permission isn't explicitly denied
- final ArraySet<String> deniedPermissions = pkg.isVendor() ?
- SystemConfig.getInstance()
- .getVendorPrivAppDenyPermissions(pkg.packageName)
- : SystemConfig.getInstance()
- .getPrivAppDenyPermissions(pkg.packageName);
+ ArraySet<String> deniedPermissions = null;
+ if (pkg.isVendor()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getVendorPrivAppDenyPermissions(pkg.packageName);
+ } else if (pkg.isProduct()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getProductPrivAppDenyPermissions(pkg.packageName);
+ } else {
+ deniedPermissions = SystemConfig.getInstance()
+ .getPrivAppDenyPermissions(pkg.packageName);
+ }
final boolean permissionViolation =
deniedPermissions == null || !deniedPermissions.contains(perm);
if (permissionViolation) {
diff --git a/tests/libs-permissions/Android.mk b/tests/libs-permissions/Android.mk
new file mode 100644
index 0000000..eb38623
--- /dev/null
+++ b/tests/libs-permissions/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product
+LOCAL_PRODUCT_MODULE := true
+LOCAL_SRC_FILES := $(call all-java-files-under, product/java)
+LOCAL_REQUIRED_MODULES := com.android.test.libs.product.xml
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
+LOCAL_SRC_FILES:= product/com.android.test.libs.product.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/libs-permissions/product/com.android.test.libs.product.xml b/tests/libs-permissions/product/com.android.test.libs.product.xml
new file mode 100644
index 0000000..0a955e9
--- /dev/null
+++ b/tests/libs-permissions/product/com.android.test.libs.product.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<permissions>
+ <library name="com.android.test.libs.product"
+ file="/product/framework/com.android.test.libs.product.jar" />
+</permissions>
diff --git a/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java b/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java
new file mode 100644
index 0000000..f49b46e
--- /dev/null
+++ b/tests/libs-permissions/product/java/com/android/test/libs/product/LibsProductTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.libs.product;
+
+/**
+ * Test class for product libs.
+ */
+public class LibsProductTest {
+
+ /**
+ * Dummpy method for testing.
+ */
+ public static void test() {
+ }
+}
diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk
index b001c8c..3c80ad8 100644
--- a/tests/privapp-permissions/Android.mk
+++ b/tests/privapp-permissions/Android.mk
@@ -29,3 +29,17 @@
LOCAL_SRC_FILES:= vendor/privapp-permissions-test.xml
include $(BUILD_PREBUILT)
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := ProductPrivAppPermissionTest
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MANIFEST_FILE := product/AndroidManifest.xml
+LOCAL_PRODUCT_MODULE := true
+LOCAL_REQUIRED_MODULES := productprivapp-permissions-test.xml
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := productprivapp-permissions-test.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
+LOCAL_SRC_FILES:= product/privapp-permissions-test.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/privapp-permissions/product/AndroidManifest.xml b/tests/privapp-permissions/product/AndroidManifest.xml
new file mode 100644
index 0000000..3d9415c
--- /dev/null
+++ b/tests/privapp-permissions/product/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.framework.permission.privapp.tests.product">
+
+ <!-- MANAGE_USB is signature|privileged -->
+ <uses-permission android:name="android.permission.MANAGE_USB"/>
+</manifest>
diff --git a/tests/privapp-permissions/product/privapp-permissions-test.xml b/tests/privapp-permissions/product/privapp-permissions-test.xml
new file mode 100644
index 0000000..f298f9d
--- /dev/null
+++ b/tests/privapp-permissions/product/privapp-permissions-test.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<permissions>
+ <privapp-permissions package="com.android.framework.permission.privapp.tests.product">
+ <permission name="android.permission.MANAGE_USB"/>
+ </privapp-permissions>
+</permissions>
diff --git a/tools/incident_report/main.cpp b/tools/incident_report/main.cpp
index bd1b973..302d739 100644
--- a/tools/incident_report/main.cpp
+++ b/tools/incident_report/main.cpp
@@ -452,9 +452,10 @@
bool adbIncidentWorkaround = true;
pid_t childPid = -1;
vector<string> sections;
+ const char* privacy = NULL;
int opt;
- while ((opt = getopt(argc, argv, "bhi:o:s:tw")) != -1) {
+ while ((opt = getopt(argc, argv, "bhi:o:s:twp:")) != -1) {
switch (opt) {
case 'b':
outputFormat = OUTPUT_PROTO;
@@ -477,6 +478,9 @@
case 'w':
adbIncidentWorkaround = false;
break;
+ case 'p':
+ privacy = optarg;
+ break;
default:
usage(stderr);
return 1;
@@ -526,7 +530,7 @@
}
// TODO: This is what the real implementation will be...
- char const** args = (char const**)malloc(sizeof(char*) * (6 + sections.size()));
+ char const** args = (char const**)malloc(sizeof(char*) * (8 + sections.size()));
int argpos = 0;
args[argpos++] = "adb";
if (adbSerial != NULL) {
@@ -535,6 +539,10 @@
}
args[argpos++] = "shell";
args[argpos++] = "incident";
+ if (privacy != NULL) {
+ args[argpos++] = "-p";
+ args[argpos++] = privacy;
+ }
for (vector<string>::const_iterator it=sections.begin(); it!=sections.end(); it++) {
args[argpos++] = it->c_str();
}