Loading core/java/android/content/res/AssetManager.java +5 −2 Original line number Diff line number Diff line Loading @@ -1157,8 +1157,11 @@ public final class AssetManager implements AutoCloseable { } } synchronized (this) { if (mObject != 0) { nativeDestroy(mObject); mObject = 0; } } } Loading core/java/android/os/ExternalVibration.java +0 −1 Original line number Diff line number Diff line Loading @@ -157,7 +157,6 @@ public class ExternalVibration implements Parcelable { out.writeInt(mUid); out.writeString(mPkg); writeAudioAttributes(mAttrs, out, flags); out.writeParcelable(mAttrs, flags); out.writeStrongBinder(mController.asBinder()); out.writeStrongBinder(mToken); } Loading core/java/android/view/inputmethod/InputMethodManager.java +30 −67 Original line number Diff line number Diff line Loading @@ -92,10 +92,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; /** Loading Loading @@ -424,13 +421,6 @@ public final class InputMethodManager { int mCursorCandStart; int mCursorCandEnd; /** * Initial startInput with {@link StartInputReason.WINDOW_FOCUS_GAIN} is executed * in a background thread. Later, if there is an actual startInput it will wait on * main thread till the background thread completes. */ private CompletableFuture<Void> mWindowFocusGainFuture; /** * The instance that has previously been sent to the input method. */ Loading Loading @@ -655,7 +645,6 @@ public final class InputMethodManager { } catch (RemoteException e) { } } } // Check focus again in case that "onWindowFocus" is called before // handling this message. if (mServedView != null && canStartInput(mServedView)) { Loading @@ -665,6 +654,7 @@ public final class InputMethodManager { startInputInner(reason, null, 0, 0, 0); } } } return; } case MSG_SEND_INPUT_EVENT: { Loading Loading @@ -1225,10 +1215,6 @@ public final class InputMethodManager { */ void clearBindingLocked() { if (DEBUG) Log.v(TAG, "Clearing binding!"); if (mWindowFocusGainFuture != null) { mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */); mWindowFocusGainFuture = null; } clearConnectionLocked(); setInputChannelLocked(null); mBindSequence = -1; Loading Loading @@ -1612,18 +1598,6 @@ public final class InputMethodManager { boolean startInputInner(@StartInputReason int startInputReason, @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode, int windowFlags) { if (startInputReason != StartInputReason.WINDOW_FOCUS_GAIN && mWindowFocusGainFuture != null) { try { mWindowFocusGainFuture.get(); } catch (ExecutionException | InterruptedException e) { // do nothing } catch (CancellationException e) { // window no longer has focus. return true; } } final View view; synchronized (mH) { view = mServedView; Loading Loading @@ -1977,19 +1951,13 @@ public final class InputMethodManager { startInputFlags |= StartInputFlags.FIRST_WINDOW_FOCUS_GAIN; } final boolean forceNewFocus1 = forceNewFocus; final int startInputFlags1 = startInputFlags; if (mWindowFocusGainFuture != null) { mWindowFocusGainFuture.cancel(false/* mayInterruptIfRunning */); } mWindowFocusGainFuture = CompletableFuture.runAsync(() -> { if (checkFocusNoStartInput(forceNewFocus1)) { if (checkFocusNoStartInput(forceNewFocus)) { // We need to restart input on the current focus view. This // should be done in conjunction with telling the system service // about the window gaining focus, to help make the transition // smooth. if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(), startInputFlags1, softInputMode, windowFlags)) { startInputFlags, softInputMode, windowFlags)) { return; } } Loading @@ -2001,14 +1969,13 @@ public final class InputMethodManager { if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput"); mService.startInputOrWindowGainedFocus( StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient, rootView.getWindowToken(), startInputFlags1, softInputMode, windowFlags, rootView.getWindowToken(), startInputFlags, softInputMode, windowFlags, null, null, 0 /* missingMethodFlags */, rootView.getContext().getApplicationInfo().targetSdkVersion); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }); } /** @hide */ Loading @@ -2023,10 +1990,6 @@ public final class InputMethodManager { // If the mCurRootView is losing window focus, release the strong reference to it // so as not to prevent it from being garbage-collected. mCurRootView = null; if (mWindowFocusGainFuture != null) { mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */); mWindowFocusGainFuture = null; } } else { if (DEBUG) { Log.v(TAG, "Ignoring onPreWindowFocus()." Loading core/tests/coretests/src/android/os/ExternalVibrationTest.java 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.os; import static junit.framework.Assert.assertEquals; import static org.mockito.Mockito.mock; import android.media.AudioAttributes; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class ExternalVibrationTest { @Test public void testSerialization() { AudioAttributes audio = new AudioAttributes.Builder().build(); IExternalVibrationController controller = mock(IExternalVibrationController.class); ExternalVibration original = new ExternalVibration( 123, // uid "pkg", audio, controller); Parcel p = Parcel.obtain(); original.writeToParcel(p, 0); p.setDataPosition(0); ExternalVibration restored = ExternalVibration.CREATOR.createFromParcel(p); assertEquals(original, restored); } } packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +43 −8 Original line number Diff line number Diff line Loading @@ -195,20 +195,32 @@ public class AppOpsControllerImpl implements AppOpsController, mNotedItems.remove(item); if (DEBUG) Log.w(TAG, "Removed item: " + item.toString()); } boolean active; // Check if the item is also active synchronized (mActiveItems) { active = getAppOpItem(mActiveItems, code, uid, packageName) != null; } if (!active) { notifySuscribers(code, uid, packageName, false); } } private void addNoted(int code, int uid, String packageName) { private boolean addNoted(int code, int uid, String packageName) { AppOpItem item; boolean createdNew = false; synchronized (mNotedItems) { item = getAppOpItem(mNotedItems, code, uid, packageName); if (item == null) { item = new AppOpItem(code, uid, packageName, System.currentTimeMillis()); mNotedItems.add(item); if (DEBUG) Log.w(TAG, "Added item: " + item.toString()); createdNew = true; } } // We should keep this so we make sure it cannot time out. mBGHandler.removeCallbacksAndMessages(item); mBGHandler.scheduleRemoval(item, NOTED_OP_TIME_DELAY_MS); return createdNew; } /** Loading Loading @@ -255,23 +267,46 @@ public class AppOpsControllerImpl implements AppOpsController, @Override public void onOpActiveChanged(int code, int uid, String packageName, boolean active) { if (updateActives(code, uid, packageName, active)) { notifySuscribers(code, uid, packageName, active); if (DEBUG) { Log.w(TAG, String.format("onActiveChanged(%d,%d,%s,%s", code, uid, packageName, Boolean.toString(active))); } boolean activeChanged = updateActives(code, uid, packageName, active); if (!activeChanged) return; // early return // Check if the item is also noted, in that case, there's no update. boolean alsoNoted; synchronized (mNotedItems) { alsoNoted = getAppOpItem(mNotedItems, code, uid, packageName) != null; } // If active is true, we only send the update if the op is not actively noted (already true) // If active is false, we only send the update if the op is not actively noted (prevent // early removal) if (!alsoNoted) { mBGHandler.post(() -> notifySuscribers(code, uid, packageName, active)); } } @Override public void onOpNoted(int code, int uid, String packageName, int result) { if (DEBUG) { Log.w(TAG, "Op: " + code + " with result " + AppOpsManager.MODE_NAMES[result]); Log.w(TAG, "Noted op: " + code + " with result " + AppOpsManager.MODE_NAMES[result] + " for package " + packageName); } if (result != AppOpsManager.MODE_ALLOWED) return; addNoted(code, uid, packageName); notifySuscribers(code, uid, packageName, true); boolean notedAdded = addNoted(code, uid, packageName); if (!notedAdded) return; // early return boolean alsoActive; synchronized (mActiveItems) { alsoActive = getAppOpItem(mActiveItems, code, uid, packageName) != null; } if (!alsoActive) { mBGHandler.post(() -> notifySuscribers(code, uid, packageName, true)); } } private void notifySuscribers(int code, int uid, String packageName, boolean active) { if (mCallbacksByCode.containsKey(code)) { if (DEBUG) Log.d(TAG, "Notifying of change in package " + packageName); for (Callback cb: mCallbacksByCode.get(code)) { cb.onActiveStateChanged(code, uid, packageName, active); } Loading @@ -295,7 +330,7 @@ public class AppOpsControllerImpl implements AppOpsController, } protected final class H extends Handler { protected class H extends Handler { H(Looper looper) { super(looper); } Loading Loading
core/java/android/content/res/AssetManager.java +5 −2 Original line number Diff line number Diff line Loading @@ -1157,8 +1157,11 @@ public final class AssetManager implements AutoCloseable { } } synchronized (this) { if (mObject != 0) { nativeDestroy(mObject); mObject = 0; } } } Loading
core/java/android/os/ExternalVibration.java +0 −1 Original line number Diff line number Diff line Loading @@ -157,7 +157,6 @@ public class ExternalVibration implements Parcelable { out.writeInt(mUid); out.writeString(mPkg); writeAudioAttributes(mAttrs, out, flags); out.writeParcelable(mAttrs, flags); out.writeStrongBinder(mController.asBinder()); out.writeStrongBinder(mToken); } Loading
core/java/android/view/inputmethod/InputMethodManager.java +30 −67 Original line number Diff line number Diff line Loading @@ -92,10 +92,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; /** Loading Loading @@ -424,13 +421,6 @@ public final class InputMethodManager { int mCursorCandStart; int mCursorCandEnd; /** * Initial startInput with {@link StartInputReason.WINDOW_FOCUS_GAIN} is executed * in a background thread. Later, if there is an actual startInput it will wait on * main thread till the background thread completes. */ private CompletableFuture<Void> mWindowFocusGainFuture; /** * The instance that has previously been sent to the input method. */ Loading Loading @@ -655,7 +645,6 @@ public final class InputMethodManager { } catch (RemoteException e) { } } } // Check focus again in case that "onWindowFocus" is called before // handling this message. if (mServedView != null && canStartInput(mServedView)) { Loading @@ -665,6 +654,7 @@ public final class InputMethodManager { startInputInner(reason, null, 0, 0, 0); } } } return; } case MSG_SEND_INPUT_EVENT: { Loading Loading @@ -1225,10 +1215,6 @@ public final class InputMethodManager { */ void clearBindingLocked() { if (DEBUG) Log.v(TAG, "Clearing binding!"); if (mWindowFocusGainFuture != null) { mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */); mWindowFocusGainFuture = null; } clearConnectionLocked(); setInputChannelLocked(null); mBindSequence = -1; Loading Loading @@ -1612,18 +1598,6 @@ public final class InputMethodManager { boolean startInputInner(@StartInputReason int startInputReason, @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode, int windowFlags) { if (startInputReason != StartInputReason.WINDOW_FOCUS_GAIN && mWindowFocusGainFuture != null) { try { mWindowFocusGainFuture.get(); } catch (ExecutionException | InterruptedException e) { // do nothing } catch (CancellationException e) { // window no longer has focus. return true; } } final View view; synchronized (mH) { view = mServedView; Loading Loading @@ -1977,19 +1951,13 @@ public final class InputMethodManager { startInputFlags |= StartInputFlags.FIRST_WINDOW_FOCUS_GAIN; } final boolean forceNewFocus1 = forceNewFocus; final int startInputFlags1 = startInputFlags; if (mWindowFocusGainFuture != null) { mWindowFocusGainFuture.cancel(false/* mayInterruptIfRunning */); } mWindowFocusGainFuture = CompletableFuture.runAsync(() -> { if (checkFocusNoStartInput(forceNewFocus1)) { if (checkFocusNoStartInput(forceNewFocus)) { // We need to restart input on the current focus view. This // should be done in conjunction with telling the system service // about the window gaining focus, to help make the transition // smooth. if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(), startInputFlags1, softInputMode, windowFlags)) { startInputFlags, softInputMode, windowFlags)) { return; } } Loading @@ -2001,14 +1969,13 @@ public final class InputMethodManager { if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput"); mService.startInputOrWindowGainedFocus( StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient, rootView.getWindowToken(), startInputFlags1, softInputMode, windowFlags, rootView.getWindowToken(), startInputFlags, softInputMode, windowFlags, null, null, 0 /* missingMethodFlags */, rootView.getContext().getApplicationInfo().targetSdkVersion); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }); } /** @hide */ Loading @@ -2023,10 +1990,6 @@ public final class InputMethodManager { // If the mCurRootView is losing window focus, release the strong reference to it // so as not to prevent it from being garbage-collected. mCurRootView = null; if (mWindowFocusGainFuture != null) { mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */); mWindowFocusGainFuture = null; } } else { if (DEBUG) { Log.v(TAG, "Ignoring onPreWindowFocus()." Loading
core/tests/coretests/src/android/os/ExternalVibrationTest.java 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.os; import static junit.framework.Assert.assertEquals; import static org.mockito.Mockito.mock; import android.media.AudioAttributes; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class ExternalVibrationTest { @Test public void testSerialization() { AudioAttributes audio = new AudioAttributes.Builder().build(); IExternalVibrationController controller = mock(IExternalVibrationController.class); ExternalVibration original = new ExternalVibration( 123, // uid "pkg", audio, controller); Parcel p = Parcel.obtain(); original.writeToParcel(p, 0); p.setDataPosition(0); ExternalVibration restored = ExternalVibration.CREATOR.createFromParcel(p); assertEquals(original, restored); } }
packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +43 −8 Original line number Diff line number Diff line Loading @@ -195,20 +195,32 @@ public class AppOpsControllerImpl implements AppOpsController, mNotedItems.remove(item); if (DEBUG) Log.w(TAG, "Removed item: " + item.toString()); } boolean active; // Check if the item is also active synchronized (mActiveItems) { active = getAppOpItem(mActiveItems, code, uid, packageName) != null; } if (!active) { notifySuscribers(code, uid, packageName, false); } } private void addNoted(int code, int uid, String packageName) { private boolean addNoted(int code, int uid, String packageName) { AppOpItem item; boolean createdNew = false; synchronized (mNotedItems) { item = getAppOpItem(mNotedItems, code, uid, packageName); if (item == null) { item = new AppOpItem(code, uid, packageName, System.currentTimeMillis()); mNotedItems.add(item); if (DEBUG) Log.w(TAG, "Added item: " + item.toString()); createdNew = true; } } // We should keep this so we make sure it cannot time out. mBGHandler.removeCallbacksAndMessages(item); mBGHandler.scheduleRemoval(item, NOTED_OP_TIME_DELAY_MS); return createdNew; } /** Loading Loading @@ -255,23 +267,46 @@ public class AppOpsControllerImpl implements AppOpsController, @Override public void onOpActiveChanged(int code, int uid, String packageName, boolean active) { if (updateActives(code, uid, packageName, active)) { notifySuscribers(code, uid, packageName, active); if (DEBUG) { Log.w(TAG, String.format("onActiveChanged(%d,%d,%s,%s", code, uid, packageName, Boolean.toString(active))); } boolean activeChanged = updateActives(code, uid, packageName, active); if (!activeChanged) return; // early return // Check if the item is also noted, in that case, there's no update. boolean alsoNoted; synchronized (mNotedItems) { alsoNoted = getAppOpItem(mNotedItems, code, uid, packageName) != null; } // If active is true, we only send the update if the op is not actively noted (already true) // If active is false, we only send the update if the op is not actively noted (prevent // early removal) if (!alsoNoted) { mBGHandler.post(() -> notifySuscribers(code, uid, packageName, active)); } } @Override public void onOpNoted(int code, int uid, String packageName, int result) { if (DEBUG) { Log.w(TAG, "Op: " + code + " with result " + AppOpsManager.MODE_NAMES[result]); Log.w(TAG, "Noted op: " + code + " with result " + AppOpsManager.MODE_NAMES[result] + " for package " + packageName); } if (result != AppOpsManager.MODE_ALLOWED) return; addNoted(code, uid, packageName); notifySuscribers(code, uid, packageName, true); boolean notedAdded = addNoted(code, uid, packageName); if (!notedAdded) return; // early return boolean alsoActive; synchronized (mActiveItems) { alsoActive = getAppOpItem(mActiveItems, code, uid, packageName) != null; } if (!alsoActive) { mBGHandler.post(() -> notifySuscribers(code, uid, packageName, true)); } } private void notifySuscribers(int code, int uid, String packageName, boolean active) { if (mCallbacksByCode.containsKey(code)) { if (DEBUG) Log.d(TAG, "Notifying of change in package " + packageName); for (Callback cb: mCallbacksByCode.get(code)) { cb.onActiveStateChanged(code, uid, packageName, active); } Loading @@ -295,7 +330,7 @@ public class AppOpsControllerImpl implements AppOpsController, } protected final class H extends Handler { protected class H extends Handler { H(Looper looper) { super(looper); } Loading