rsbinder 0.6.1

rsbinder provides crates implemented in pure Rust that make Binder IPC available on both Android and Linux.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
// Copyright 2022 Jeff Kim <hiking90@gmail.com>
// SPDX-License-Identifier: Apache-2.0

/*
 * 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.
 */

//! Core binder functionality and traits.
//!
//! This module provides the fundamental types and traits for binder IPC,
//! including interface definitions, binder object management, and transaction
//! handling. It forms the foundation for all binder communication.

use std::any::Any;
use std::borrow::Borrow;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::sync::{self, Arc};

use crate::{error::*, parcel::*, proxy, sys};

/// Binder action to perform.
///
/// This must be a number between [`FIRST_CALL_TRANSACTION`] and
/// [`LAST_CALL_TRANSACTION`].
pub type TransactionCode = u32;

/// Additional operation flags.
///
/// `FLAG_*` values.
pub type TransactionFlags = u32;

/// Corresponds to TF_ONE_WAY -- an asynchronous call.
pub const FLAG_ONEWAY: TransactionFlags = sys::transaction_flags_TF_ONE_WAY;
/// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made.
pub const FLAG_CLEAR_BUF: TransactionFlags = sys::transaction_flags_TF_CLEAR_BUF;
/// Set to the vendor flag if we are building for the VNDK, 0 otherwise
pub const FLAG_PRIVATE_LOCAL: TransactionFlags = 0;
pub const FLAG_PRIVATE_VENDOR: TransactionFlags = FLAG_PRIVATE_LOCAL;

const fn b_pack_chars(c1: char, c2: char, c3: char, c4: char) -> u32 {
    ((c1 as u32) << 24) | ((c2 as u32) << 16) | ((c3 as u32) << 8) | (c4 as u32)
}

pub const FIRST_CALL_TRANSACTION: u32 = 0x00000001;
pub const LAST_CALL_TRANSACTION: u32 = 0x00ffffff;

pub const PING_TRANSACTION: u32 = b_pack_chars('_', 'P', 'N', 'G');
pub const DUMP_TRANSACTION: u32 = b_pack_chars('_', 'D', 'M', 'P');
pub const SHELL_COMMAND_TRANSACTION: u32 = b_pack_chars('_', 'C', 'M', 'D');
// It must be used to ask binder's interface name.
pub const INTERFACE_TRANSACTION: u32 = b_pack_chars('_', 'N', 'T', 'F');
pub const SYSPROPS_TRANSACTION: u32 = b_pack_chars('_', 'S', 'P', 'R');
pub const EXTENSION_TRANSACTION: u32 = b_pack_chars('_', 'E', 'X', 'T');
pub const DEBUG_PID_TRANSACTION: u32 = b_pack_chars('_', 'P', 'I', 'D');
pub const SET_RPC_CLIENT_TRANSACTION: u32 = b_pack_chars('_', 'R', 'P', 'C');

pub const START_RECORDING_TRANSACTION: u32 = b_pack_chars('_', 'S', 'R', 'D');
pub const STOP_RECORDING_TRANSACTION: u32 = b_pack_chars('_', 'E', 'R', 'D');

// See android.os.IBinder.TWEET_TRANSACTION
// Most importantly, messages can be anything not exceeding 130 UTF-8
// characters, and callees should exclaim "jolly good message old boy!"
pub const TWEET_TRANSACTION: u32 = b_pack_chars('_', 'T', 'W', 'T');

// See android.os.IBinder.LIKE_TRANSACTION
// Improve binder self-esteem.
pub const LIKE_TRANSACTION: u32 = b_pack_chars('_', 'L', 'I', 'K');

pub const INTERFACE_HEADER: u32 = b_pack_chars('S', 'Y', 'S', 'T');

/// Base trait for all binder interfaces.
///
/// This trait allows conversion of a binder interface trait object into an
/// IBinder object for IPC calls. All binder remotable interfaces (i.e., AIDL
/// interfaces) must implement this trait to participate in binder IPC.
///
/// Equivalent to `IInterface` in Android's C++ binder implementation.
pub trait Interface: Send + Sync {
    /// Convert this binder object into a generic [`SIBinder`] reference.
    fn as_binder(&self) -> SIBinder {
        log::error!(
            "as_binder() called on non-Binder object of type {}. \
             This is a programmer error - only Binder objects should implement Interface.",
            std::any::type_name::<Self>()
        );
        // This should never happen in correct code, but we want a clear error
        // rather than undefined behavior
        unreachable!(
            "as_binder() must be overridden by types that can be converted to SIBinder. \
             Type: {}",
            std::any::type_name::<Self>()
        )
    }

    /// Dump transaction handler for this Binder object.
    ///
    /// This handler is a no-op by default and should be implemented for each
    /// Binder service struct that wishes to respond to dump transactions.
    fn dump(&self, _writer: &mut dyn std::io::Write, _args: &[String]) -> Result<()> {
        Ok(())
    }
}

/// Trait for converting a generic Binder object into a specific Binder
///
/// # Example
///
/// For Binder interface `IFoo`, the following implementation should be made:
/// ```no_run
/// # use rsbinder::{FromIBinder, SIBinder, Interface, Result, Strong};
/// # trait IFoo : Interface {}
/// impl FromIBinder for dyn IFoo {
///     fn try_from(ibinder: SIBinder) -> Result<Strong<Self>> {
///         // ...
///         # Err(rsbinder::StatusCode::Ok)
///     }
/// }
/// ```
pub trait FromIBinder: Interface {
    /// Try to interpret a generic Binder object as this interface.
    ///
    /// Returns a trait object for the `Self` interface if this object
    /// implements that interface.
    fn try_from(ibinder: SIBinder) -> Result<Strong<Self>>;
}

/// Interface for receiving a notification when a binder object is no longer
/// valid.
///
/// This trait corresponds to the parts of the interface of the C++ `DeathRecipient`
/// Callback interface for binder death notifications.
///
/// Implement this trait to receive notifications when a remote binder object dies.
/// This is essential for cleanup and error handling in distributed systems.
pub trait DeathRecipient: Send + Sync {
    /// Called when the monitored binder object has died.
    fn binder_died(&self, who: &WIBinder);
}

/// Core interface for binder objects, both local and remote.
///
/// This trait corresponds to the public interface of the C++ `IBinder` class,
/// providing the fundamental operations available on all binder objects
/// regardless of whether they represent local services or remote proxies.
pub trait IBinder: Any + Send + Sync {
    /// Register the recipient for a notification if this binder
    /// goes away. If this binder object unexpectedly goes away
    /// (typically because its hosting process has been killed),
    /// then the `DeathRecipient`'s callback will be called.
    ///
    /// You will only receive death notifications for remote binders,
    /// as local binders by definition can't die without you dying as well.
    /// Trying to use this function on a local binder will result in an
    /// INVALID_OPERATION code being returned and nothing happening.
    ///
    /// This link always holds a weak reference to its recipient.
    fn link_to_death(&self, recipient: sync::Weak<dyn DeathRecipient>) -> Result<()>;

    /// Remove a previously registered death notification.
    /// The recipient will no longer be called if this object
    /// dies.
    fn unlink_to_death(&self, recipient: sync::Weak<dyn DeathRecipient>) -> Result<()>;

    /// Send a ping transaction to this object
    fn ping_binder(&self) -> Result<()>;

    /// To support dynamic interface cast, we need to know the interface
    fn as_any(&self) -> &dyn Any;

    /// To convert the interface to a transactable object
    fn as_transactable(&self) -> Option<&dyn Transactable>;

    /// Retrieve the descriptor of this object.
    fn descriptor(&self) -> &str;
    /// Retrieve if this object is remote.
    fn is_remote(&self) -> bool;

    /// Retrieve the stability level of this binder object.
    fn stability(&self) -> Stability {
        Stability::default()
    }

    /// Return the extension binder object, if set. Returns None if no extension is set.
    fn get_extension(&self) -> Result<Option<SIBinder>> {
        Ok(None)
    }

    /// Set the extension binder object.
    fn set_extension(&self, _extension: &SIBinder) -> Result<()> {
        Err(StatusCode::InvalidOperation)
    }

    fn inc_strong(&self, strong: &SIBinder) -> Result<()>;
    fn attempt_inc_strong(&self) -> bool;
    fn dec_strong(&self, strong: Option<ManuallyDrop<SIBinder>>) -> Result<()>;
    fn inc_weak(&self, weak: &WIBinder) -> Result<()>;
    fn dec_weak(&self) -> Result<()>;
}

impl dyn IBinder {
    /// Convert this binder object into a proxy binder object.
    pub fn as_proxy(&self) -> Option<&proxy::ProxyHandle> {
        self.as_any().downcast_ref::<proxy::ProxyHandle>()
    }
}

impl std::fmt::Debug for dyn IBinder {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:?}", self.as_any())
    }
}

/// Trait for local services that can be exposed via binder IPC.
///
/// Objects implementing this trait can be wrapped in a `Binder<T>` to create
/// a binder service that can receive and handle incoming transactions.
///
/// This is typically auto-generated from AIDL definitions and should not
/// be implemented manually. The AIDL compiler generates the necessary
/// transaction handling code that implements this trait.
pub trait Remotable: Send + Sync {
    /// The Binder interface descriptor string.
    ///
    /// This string is a unique identifier for a Binder interface, and should be
    /// the same between all implementations of that interface.
    fn descriptor() -> &'static str
    where
        Self: Sized;

    /// Handle and reply to a request to invoke a transaction on this object.
    ///
    /// `reply` may be [`None`] if the sender does not expect a reply.
    fn on_transact(
        &self,
        code: TransactionCode,
        reader: &mut Parcel,
        reply: &mut Parcel,
    ) -> Result<()>;

    /// Handle a request to invoke the dump transaction on this
    /// object.
    fn on_dump(&self, writer: &mut dyn std::io::Write, args: &[String]) -> Result<()>;
}

/// A transactable object that can be used to process Binder commands.
pub trait Transactable: Send + Sync {
    fn transact(
        &self,
        code: TransactionCode,
        reader: &mut Parcel,
        reply: &mut Parcel,
    ) -> Result<()>;
}

/// Implemented by sync interfaces to specify what the associated async interface is.
/// Generic to handle the fact that async interfaces are generic over a thread pool.
///
/// The binder in any object implementing this trait should be compatible with the
/// `Target` associated type, and using `FromIBinder` to convert it to the target
/// should not fail.
pub trait ToAsyncInterface<P>
where
    Self: Interface,
    Self::Target: FromIBinder,
{
    /// The async interface associated with this sync interface.
    type Target: ?Sized;
}

/// Implemented by async interfaces to specify what the associated sync interface is.
///
/// The binder in any object implementing this trait should be compatible with the
/// `Target` associated type, and using `FromIBinder` to convert it to the target
/// should not fail.
pub trait ToSyncInterface
where
    Self: Interface,
    Self::Target: FromIBinder,
{
    /// The sync interface associated with this async interface.
    type Target: ?Sized;
}

/// Interface stability promise
///
/// An interface can promise to be a stable vendor interface ([`Stability::Vintf`]), or
/// makes no stability guarantees ([`Stability::Local`]). [`Stability::System`] is
/// the default stability, matching Android's `getLocalLevel()` for non-VNDK builds.
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub enum Stability {
    /// Default stability, visible to other modules in the same compilation
    /// context (e.g. modules on system.img)
    Local,
    Vendor,
    #[default]
    System,

    /// A Vendor Interface Object, which promises to be stable
    Vintf,
}

impl Stability {
    /// Android bitmask-compatible verification.
    ///
    /// Checks whether `self` (provider) includes the `required` stability level.
    /// e.g., Vintf includes all levels. System and Vendor are independent domains.
    pub fn includes(&self, required: Stability) -> bool {
        let provided: i32 = (*self).into();
        let required: i32 = required.into();
        (provided & required) == required
    }
}

// Android 12 version uses "Category" as the stability format for passed on the wire lines,
// whereas other versions do not. Therefore, we can use the android_properties crate
// to determine the Android version and perform different handling accordingly.
// http://aospxref.com/android-11.0.0_r21/xref/frameworks/native/libs/binder/include/binder/Stability.h
// http://aospxref.com/android-12.0.0_r3/xref/frameworks/native/include/binder/Stability.h
// http://aospxref.com/android-13.0.0_r3/xref/frameworks/native/libs/binder/include/binder/Stability.h
// http://aospxref.com/android-14.0.0_r2/xref/frameworks/native/libs/binder/include/binder/Stability.h
impl From<Stability> for i32 {
    fn from(stability: Stability) -> i32 {
        use Stability::*;

        let stability = match stability {
            Local => 0,
            Vendor => 0b000011,
            System => 0b001100,
            Vintf => 0b111111,
        };

        #[cfg(target_os = "android")]
        {
            let android_sdk_version = crate::get_android_sdk_version();
            if android_sdk_version == 31 || android_sdk_version == 32 {
                stability | 0x0c000000
            } else {
                stability
            }
        }
        #[cfg(not(target_os = "android"))]
        stability
    }
}

impl TryFrom<i32> for Stability {
    type Error = StatusCode;
    fn try_from(stability: i32) -> Result<Stability> {
        use Stability::*;

        // Try matching as raw Level value first (Android 11, 13+)
        let level = if stability <= 0xFF {
            stability
        } else {
            // Try extracting level from Category repr format (Android 12).
            // Category struct on little-endian: { version: u8, reserved: [u8; 2], level: u8 }
            // repr() = (level << 24) | version
            (stability >> 24) & 0xFF
        };

        match level {
            0 => Ok(Local),
            0b000011 => Ok(Vendor),
            0b001100 => Ok(System),
            0b111111 => Ok(Vintf),
            _ => {
                log::error!("Stability value is invalid: {stability:#X}");
                Err(StatusCode::BadValue)
            }
        }
    }
}

/// Strong reference to a binder object.
pub struct SIBinder {
    inner: Arc<dyn IBinder>,
}

impl SIBinder {
    pub fn new(data: Arc<dyn IBinder>) -> Result<Self> {
        WIBinder::new(data)?.upgrade()
    }

    fn new_with_inner(inner: Arc<dyn IBinder>) -> Result<Self> {
        let this = Self { inner };
        this.increase()?;
        Ok(this)
    }

    pub(crate) fn into_raw(self) -> *const dyn IBinder {
        let inner = Arc::clone(&self.inner);
        let raw = Arc::into_raw(inner);
        std::mem::forget(self);
        raw
    }

    pub(crate) fn from_raw(raw: *const dyn IBinder) -> Self {
        let inner = unsafe { Arc::from_raw(raw) };
        Self { inner }
    }

    pub fn downgrade(this: &Self) -> WIBinder {
        WIBinder::new_with_inner(Arc::clone(&this.inner))
    }

    /// Retrieve the stability level of the underlying binder object.
    pub fn stability(&self) -> Stability {
        self.inner.stability()
    }

    pub(crate) fn increase(&self) -> Result<()> {
        self.inner.inc_strong(self)
    }

    pub(crate) fn attempt_increase(&self) -> bool {
        self.inner.attempt_inc_strong()
    }

    pub(crate) fn decrease(&self) -> Result<()> {
        self.inner.dec_strong(None)
    }

    pub(crate) fn decrease_drop(this: ManuallyDrop<Self>) -> Result<()> {
        let inner = Arc::clone(&this.inner);
        inner.dec_strong(Some(this))
    }

    /// Try to convert this Binder object into a trait object for the given
    /// Binder interface.
    ///
    /// If this object does not implement the expected interface, the error
    /// `StatusCode::BadType` is returned.
    pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> {
        FromIBinder::try_from(self)
    }
}

impl Debug for SIBinder {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        f.debug_struct("SIBinder")
            .field("descriptor", &self.descriptor())
            .field("ptr", &Arc::as_ptr(&self.inner))
            .finish()
    }
}

impl Clone for SIBinder {
    fn clone(&self) -> Self {
        Self::new_with_inner(Arc::clone(&self.inner))
            .expect("Failed to clone SIBinder: inc_strong should not fail on existing reference")
    }
}

impl Drop for SIBinder {
    fn drop(&mut self) {
        self.decrease()
            .map_err(|err| {
                log::error!("Error in SIBinder::drop() is {err:?}");
            })
            .ok();
    }
}

impl Deref for SIBinder {
    type Target = dyn IBinder;
    fn deref(&self) -> &Self::Target {
        self.inner.deref()
    }
}

impl PartialEq for SIBinder {
    fn eq(&self, other: &Self) -> bool {
        Arc::ptr_eq(&self.inner, &other.inner)
    }
}

impl Eq for SIBinder {}

/// Weak reference to a binder object.
pub struct WIBinder {
    inner: Arc<dyn IBinder>,
}

impl WIBinder {
    pub(crate) fn new(inner: Arc<dyn IBinder>) -> Result<Self> {
        let this = Self { inner };
        this.inner.inc_weak(&this)?;

        Ok(this)
    }

    fn new_with_inner(inner: Arc<dyn IBinder>) -> Self {
        let this = Self { inner };
        this.increase();
        this
    }

    pub(crate) fn increase(&self) {
        self.inner.inc_weak(self).ok();
    }

    pub(crate) fn decrease(&self) {
        self.inner.dec_weak().ok();
    }

    pub fn upgrade(&self) -> Result<SIBinder> {
        SIBinder::new_with_inner(Arc::clone(&self.inner))
    }
}

impl Debug for WIBinder {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        f.debug_struct("WIBinder")
            .field("self", &(self as *const WIBinder))
            .field("descriptor", &self.inner.descriptor())
            .field("inner_ptr", &Arc::as_ptr(&self.inner))
            .finish()
    }
}

impl Clone for WIBinder {
    fn clone(&self) -> Self {
        Self::new_with_inner(Arc::clone(&self.inner))
    }
}

impl Drop for WIBinder {
    fn drop(&mut self) {
        self.decrease();
    }
}

impl PartialEq for WIBinder {
    fn eq(&self, other: &Self) -> bool {
        Arc::ptr_eq(&self.inner, &other.inner)
    }
}

/// Strong reference to a binder object
pub struct Strong<I: FromIBinder + ?Sized>(Box<I>);

impl<I: FromIBinder + ?Sized> Strong<I> {
    /// Create a new strong reference to the provided binder object
    pub fn new(binder: Box<I>) -> Self {
        Self(binder)
    }

    /// Construct a new weak reference to this binder
    pub fn downgrade(this: &Strong<I>) -> Weak<I> {
        Weak::new(this)
    }

    /// Convert this synchronous binder handle into an asynchronous one.
    pub fn into_async<P>(self) -> Strong<<I as ToAsyncInterface<P>>::Target>
    where
        I: ToAsyncInterface<P>,
    {
        // By implementing the ToAsyncInterface trait, it is guaranteed that the binder
        // object is also valid for the target type.
        FromIBinder::try_from(self.0.as_binder())
            .expect("ToAsyncInterface guarantees binder compatibility")
    }

    /// Convert this asynchronous binder handle into a synchronous one.
    pub fn into_sync(self) -> Strong<<I as ToSyncInterface>::Target>
    where
        I: ToSyncInterface,
    {
        // By implementing the ToSyncInterface trait, it is guaranteed that the binder
        // object is also valid for the target type.
        FromIBinder::try_from(self.0.as_binder())
            .expect("ToSyncInterface guarantees binder compatibility")
    }
}

impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
    fn clone(&self) -> Self {
        // Since we hold a strong reference, we should always be able to create
        // a new strong reference to the same interface type, so try_from()
        // should never fail here.
        FromIBinder::try_from(self.0.as_binder())
            .expect("Failed to clone Strong<I>: existing strong reference guarantees valid binder")
    }
}

impl<I: FromIBinder + ?Sized> Borrow<I> for Strong<I> {
    fn borrow(&self) -> &I {
        &self.0
    }
}

impl<I: FromIBinder + ?Sized> AsRef<I> for Strong<I> {
    fn as_ref(&self) -> &I {
        &self.0
    }
}

impl<I: FromIBinder + ?Sized> Deref for Strong<I> {
    type Target = I;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<I: FromIBinder + Debug + ?Sized> Debug for Strong<I> {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        Debug::fmt(&**self, f)
    }
}

impl<I: FromIBinder + ?Sized> PartialEq for Strong<I> {
    fn eq(&self, other: &Self) -> bool {
        self.0.as_binder().eq(&other.0.as_binder())
    }
}

impl<I: FromIBinder + ?Sized> Eq for Strong<I> {}

/// Weak reference to a binder object
#[derive(Debug)]
pub struct Weak<I: FromIBinder + ?Sized> {
    weak_binder: WIBinder,
    interface_type: PhantomData<I>,
}

impl<I: FromIBinder + ?Sized> Weak<I> {
    /// Construct a new weak reference from a strong reference
    fn new(binder: &Strong<I>) -> Self {
        let weak_binder = SIBinder::downgrade(&binder.as_binder());
        Weak {
            weak_binder,
            interface_type: PhantomData,
        }
    }

    /// Upgrade this weak reference to a strong reference if the binder object
    /// is still alive
    pub fn upgrade(&self) -> Result<Strong<I>> {
        self.weak_binder.upgrade().and_then(FromIBinder::try_from)
    }
}

impl<I: FromIBinder + ?Sized> Clone for Weak<I> {
    fn clone(&self) -> Self {
        Self {
            weak_binder: self.weak_binder.clone(),
            interface_type: PhantomData,
        }
    }
}

#[cfg(test)]
mod tests {
    // use crate::proxy::ProxyHandle;
    use super::*;

    #[test]
    fn test_strong() -> Result<()> {
        // let descriptor = "interface";
        // let strong = SIBinder::new(Box::new(ProxyHandle::new(0, descriptor, Default::default())), descriptor);
        // assert_eq!(strong.inner.strong.load(Ordering::Relaxed), 1);

        // let strong2 = strong.clone();
        // assert_eq!(strong2.inner.strong.load(Ordering::Relaxed), 2);

        // let weak = SIBinder::downgrade(&strong);

        // assert_eq!(weak.inner.strong.load(Ordering::Relaxed), 1);

        // let strong = weak.upgrade();
        // assert_eq!(strong.inner.strong.load(Ordering::Relaxed), 2);
        // SIBinder::downgrade(&strong);
        // assert_eq!(*strong2.0.lock().unwrap(), 101);

        // let weak = strong2.downgrade();

        // assert_eq!(*weak.0.lock().unwrap(), 1);

        Ok(())
    }

    #[test]
    fn test_b_pack_chars() {
        assert_eq!(b_pack_chars('_', 'P', 'N', 'G'), PING_TRANSACTION);
        assert_eq!(b_pack_chars('_', 'D', 'M', 'P'), DUMP_TRANSACTION);
        assert_eq!(b_pack_chars('_', 'C', 'M', 'D'), SHELL_COMMAND_TRANSACTION);
        assert_eq!(b_pack_chars('_', 'N', 'T', 'F'), INTERFACE_TRANSACTION);
        assert_eq!(b_pack_chars('_', 'S', 'P', 'R'), SYSPROPS_TRANSACTION);
        assert_eq!(b_pack_chars('_', 'E', 'X', 'T'), EXTENSION_TRANSACTION);
        assert_eq!(b_pack_chars('_', 'P', 'I', 'D'), DEBUG_PID_TRANSACTION);
        assert_eq!(b_pack_chars('_', 'R', 'P', 'C'), SET_RPC_CLIENT_TRANSACTION);
        assert_eq!(
            b_pack_chars('_', 'S', 'R', 'D'),
            START_RECORDING_TRANSACTION
        );
        assert_eq!(b_pack_chars('_', 'E', 'R', 'D'), STOP_RECORDING_TRANSACTION);
        assert_eq!(b_pack_chars('_', 'T', 'W', 'T'), TWEET_TRANSACTION);
        assert_eq!(b_pack_chars('_', 'L', 'I', 'K'), LIKE_TRANSACTION);
    }
}

#[cfg(test)]
mod stability_tests {
    use super::*;

    // === Wire value tests ===
    #[test]
    fn test_stability_wire_values() {
        assert_eq!(Into::<i32>::into(Stability::Local), 0);
        assert_eq!(Into::<i32>::into(Stability::Vendor), 0b000011);
        assert_eq!(Into::<i32>::into(Stability::System), 0b001100);
        assert_eq!(Into::<i32>::into(Stability::Vintf), 0b111111);
    }

    // === TryFrom round-trip tests ===
    #[test]
    fn test_stability_roundtrip() {
        for s in [
            Stability::Local,
            Stability::Vendor,
            Stability::System,
            Stability::Vintf,
        ] {
            let wire: i32 = s.into();
            assert_eq!(Stability::try_from(wire).unwrap(), s);
        }
    }

    #[test]
    fn test_stability_category_format() {
        // Android 12 Category repr: level in byte 3 (big end on little-endian)
        // Category{version=1, reserved=[0,0], level} → repr = (level << 24) | version
        let category = |level: i32, version: i32| -> i32 { (level << 24) | version };

        assert_eq!(
            Stability::try_from(category(0b000011, 1)).unwrap(),
            Stability::Vendor
        );
        assert_eq!(
            Stability::try_from(category(0b001100, 1)).unwrap(),
            Stability::System
        );
        assert_eq!(
            Stability::try_from(category(0b111111, 1)).unwrap(),
            Stability::Vintf
        );

        // Different version values should also work
        assert_eq!(
            Stability::try_from(category(0b001100, 12)).unwrap(),
            Stability::System
        );

        // rsbinder's own Android 12 format: level | 0x0c000000
        assert_eq!(
            Stability::try_from(0b001100 | 0x0c000000_i32).unwrap(),
            Stability::System
        );
    }

    #[test]
    fn test_stability_invalid_value() {
        assert_eq!(Stability::try_from(0x7F).unwrap_err(), StatusCode::BadValue);
        assert_eq!(Stability::try_from(0x01).unwrap_err(), StatusCode::BadValue);
    }

    // === Bitmask verification tests ===
    #[test]
    fn test_stability_includes() {
        // Local is included by all stability levels
        assert!(Stability::Local.includes(Stability::Local));
        assert!(Stability::Vendor.includes(Stability::Local));
        assert!(Stability::System.includes(Stability::Local));
        assert!(Stability::Vintf.includes(Stability::Local));

        // Vendor and System are independent domains
        assert!(!Stability::Vendor.includes(Stability::System));
        assert!(!Stability::System.includes(Stability::Vendor));

        // Vintf includes all levels
        assert!(Stability::Vintf.includes(Stability::Vendor));
        assert!(Stability::Vintf.includes(Stability::System));
        assert!(Stability::Vintf.includes(Stability::Vintf));

        // Self-inclusion
        assert!(Stability::Vendor.includes(Stability::Vendor));
        assert!(Stability::System.includes(Stability::System));
    }
}